From 7112b9543af8d198503e213af9487a106093bae4 Mon Sep 17 00:00:00 2001 From: songfei Date: Wed, 28 Dec 2016 10:39:42 +0800 Subject: [PATCH 1/6] =?UTF-8?q?1.=E6=9B=B4=E6=8D=A2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E8=BF=9E=E6=8E=A5=E6=B1=A0=20c3p0=20=3D>=20durid=202.?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=B8=BA?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- disconf-web/.gitignore | 1 + disconf-web/deploy/deploy.sh | 0 disconf-web/pom.xml | 7 ++- disconf-web/profile/rd/jdbc-mysql.properties | 23 +++++---- disconf-web/sql/1-init_data.sql | 2 + disconf-web/sql/201512/20151225.sql | 2 + disconf-web/sql/20160701/20160701.sql | 2 + .../myconfig/applicationContext-dbconfig.xml | 50 +++++++++++++------ pom.xml | 6 +++ 9 files changed, 68 insertions(+), 25 deletions(-) mode change 100644 => 100755 disconf-web/deploy/deploy.sh diff --git a/disconf-web/.gitignore b/disconf-web/.gitignore index bee5c04ad..e58a7e901 100644 --- a/disconf-web/.gitignore +++ b/disconf-web/.gitignore @@ -5,6 +5,7 @@ /log /pom.xml.releaseBackup /output +/deploy/src /.pydevproject /*tmp /*.iml diff --git a/disconf-web/deploy/deploy.sh b/disconf-web/deploy/deploy.sh old mode 100644 new mode 100755 diff --git a/disconf-web/pom.xml b/disconf-web/pom.xml index c6628aab5..a87b7431f 100644 --- a/disconf-web/pom.xml +++ b/disconf-web/pom.xml @@ -191,10 +191,15 @@ javax.annotation-api - + + + com.alibaba + druid + commons-beanutils diff --git a/disconf-web/profile/rd/jdbc-mysql.properties b/disconf-web/profile/rd/jdbc-mysql.properties index ea0faec79..4f6f4012f 100644 --- a/disconf-web/profile/rd/jdbc-mysql.properties +++ b/disconf-web/profile/rd/jdbc-mysql.properties @@ -1,11 +1,16 @@ -jdbc.driverClassName=com.mysql.jdbc.Driver - -jdbc.db_0.url=jdbc:mysql://127.0.0.1:3306/disconf?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=false +jdbc.db_0.url=jdbc:mysql://192.168.30.71:3306/disconf?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=false jdbc.db_0.username=root -jdbc.db_0.password=123456 +jdbc.db_0.password=xbntest -jdbc.maxPoolSize=20 -jdbc.minPoolSize=10 -jdbc.initialPoolSize=10 -jdbc.idleConnectionTestPeriod=1200 -jdbc.maxIdleTime=3600 \ No newline at end of file +jdbc.filters=stat +jdbc.maxActive=20 +jdbc.initialSize=1 +jdbc.maxWait=60000 +jdbc.minIdle=1 +jdbc.timeBetweenEvictionRunsMillis=60000 +jdbc.minEvictableIdleTimeMillis=300000 +jdbc.testWhileIdle=true +jdbc.testOnBorrow=false +jdbc.testOnReturn=false +jdbc.poolPreparedStatements=true +jdbc.maxOpenPreparedStatements=20 diff --git a/disconf-web/sql/1-init_data.sql b/disconf-web/sql/1-init_data.sql index 9fc37dbab..0869ce1d6 100644 --- a/disconf-web/sql/1-init_data.sql +++ b/disconf-web/sql/1-init_data.sql @@ -1,3 +1,5 @@ +USE `disconf`; + INSERT INTO `app` (`app_id`, `name`, `description`, `create_time`, `update_time`, `emails`) VALUES (2, 'disconf_demo', 'disconf demo', '99991231235959', '99991231235959', ''); diff --git a/disconf-web/sql/201512/20151225.sql b/disconf-web/sql/201512/20151225.sql index 025c0654f..4f4ca9bd6 100644 --- a/disconf-web/sql/201512/20151225.sql +++ b/disconf-web/sql/201512/20151225.sql @@ -1,3 +1,5 @@ +USE `disconf`; + CREATE TABLE `config_history` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `config_id` BIGINT NOT NULL, diff --git a/disconf-web/sql/20160701/20160701.sql b/disconf-web/sql/20160701/20160701.sql index c56ff9408..e8af637c0 100644 --- a/disconf-web/sql/20160701/20160701.sql +++ b/disconf-web/sql/20160701/20160701.sql @@ -1,3 +1,5 @@ +USE `disconf`; + ALTER TABLE `config_history` ADD COLUMN `update_by` BIGINT(20) NULL DEFAULT NULL AFTER `create_time`; diff --git a/disconf-web/src/main/resources/myconfig/applicationContext-dbconfig.xml b/disconf-web/src/main/resources/myconfig/applicationContext-dbconfig.xml index d0e28ce67..abe4460d6 100644 --- a/disconf-web/src/main/resources/myconfig/applicationContext-dbconfig.xml +++ b/disconf-web/src/main/resources/myconfig/applicationContext-dbconfig.xml @@ -12,32 +12,52 @@ - - ${jdbc.driverClassName} + class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> + + + ${jdbc.filters} + + + ${jdbc.maxActive} + + + ${jdbc.initialSize} + + + ${jdbc.maxWait} - - ${jdbc.initialPoolSize} + + ${jdbc.minIdle} - - ${jdbc.maxPoolSize} + + ${jdbc.timeBetweenEvictionRunsMillis} - - ${jdbc.minPoolSize} + + ${jdbc.minEvictableIdleTimeMillis} - - ${jdbc.idleConnectionTestPeriod} + + ${jdbc.testWhileIdle} - - ${jdbc.maxIdleTime} + + ${jdbc.testOnBorrow} + + ${jdbc.testOnReturn} + + + ${jdbc.poolPreparedStatements} + + + ${jdbc.maxOpenPreparedStatements} + + - + ${jdbc.db_0.url} - + ${jdbc.db_0.username} diff --git a/pom.xml b/pom.xml index fc62fef0f..00c6c60fd 100644 --- a/pom.xml +++ b/pom.xml @@ -86,6 +86,12 @@ 0.9.1.2 + + com.alibaba + druid + 1.0.27 + + com.google.code.gson gson From 4412e30706cdb11bb9918ae96dbcdcb88948f959 Mon Sep 17 00:00:00 2001 From: songfei Date: Fri, 24 Feb 2017 16:17:19 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E9=85=8D=E5=90=88=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E8=BF=90=E7=BB=B4=E5=B9=B3=E5=8F=B0=EF=BC=8C=E6=9A=82?= =?UTF-8?q?=E6=97=B6=E5=BC=80=E6=94=BE=E6=89=B9=E9=87=8F=E6=89=93=E5=8C=85?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/myconfig/spring-servlet-interceptor.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/disconf-web/src/main/resources/myconfig/spring-servlet-interceptor.xml b/disconf-web/src/main/resources/myconfig/spring-servlet-interceptor.xml index b16504467..8eca8bc31 100644 --- a/disconf-web/src/main/resources/myconfig/spring-servlet-interceptor.xml +++ b/disconf-web/src/main/resources/myconfig/spring-servlet-interceptor.xml @@ -30,6 +30,8 @@ /api/config/file /api/config/list /api/config/simple/list + + /api/web/config/downloadfilebatch From 211ec5270d404c84f5f9b4b3ca5315b94edbe968 Mon Sep 17 00:00:00 2001 From: songfei Date: Wed, 2 Aug 2017 18:13:19 +0800 Subject: [PATCH 3/6] =?UTF-8?q?1.=20=E4=BF=AE=E5=A4=8DXML=E3=80=81?= =?UTF-8?q?=E6=97=A0=E6=B3=A8=E8=A7=A3=E6=96=B9=E5=BC=8F=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6reload=E6=97=B6=E3=80=81?= =?UTF-8?q?=E4=B8=8D=E6=94=AF=E6=8C=81=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84Bug=202.=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84=E3=80=81=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=A4=9A=E4=BD=99=E7=9A=84=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/baidu/disconf/client/DisconfMgr.java | 34 +- .../baidu/disconf/client/DisconfMgrBean.java | 2 +- .../ReloadablePropertiesFactoryBean.java | 28 +- .../common/model/DisconfCenterFile.java | 2 +- .../baidu/disconf/client/scan/ScanMgr.java | 8 + .../disconf/client/scan/impl/ScanMgrImpl.java | 5 + ...StaticScannerNonAnnotationFileMgrImpl.java | 46 ++ disconf-web/html/build.py | 84 --- disconf-web/html/build.sh | 19 - disconf-web/html/index.html | 23 +- disconf-web/html/login.html | 24 +- disconf-web/html/main.html | 24 +- disconf-web/html/mainTpl/index.tpl.html | 24 - disconf-web/html/mainTpl/login.tpl.html | 55 -- disconf-web/html/mainTpl/main.tpl.html | 91 --- disconf-web/html/mainTpl/modifyFile.tpl.html | 155 ----- disconf-web/html/mainTpl/modifyItem.tpl.html | 95 --- .../html/mainTpl/modifypassword.tpl.html | 64 -- disconf-web/html/mainTpl/newapp.tpl.html | 66 -- .../html/mainTpl/newconfig_file.tpl.html | 150 ---- .../html/mainTpl/newconfig_item.tpl.html | 91 --- disconf-web/html/modifyFile.html | 24 +- disconf-web/html/modifyItem.html | 24 +- disconf-web/html/modifypassword.html | 24 +- disconf-web/html/newapp.html | 24 +- disconf-web/html/newconfig_file.html | 24 +- disconf-web/html/newconfig_item.html | 25 +- disconf-web/html/tools/gen_html.bat | 7 - disconf-web/html/tools/gen_html.sh | 2 - .../html/tools/node_modules/ejs/.gitmodules | 0 .../html/tools/node_modules/ejs/.npmignore | 4 - .../html/tools/node_modules/ejs/.travis.yml | 7 - .../html/tools/node_modules/ejs/History.md | 138 ---- .../html/tools/node_modules/ejs/Makefile | 23 - .../html/tools/node_modules/ejs/Readme.md | 188 ----- .../html/tools/node_modules/ejs/benchmark.js | 14 - .../html/tools/node_modules/ejs/ejs.js | 647 ------------------ .../html/tools/node_modules/ejs/ejs.min.js | 1 - .../node_modules/ejs/examples/client.html | 24 - .../node_modules/ejs/examples/functions.ejs | 9 - .../node_modules/ejs/examples/functions.js | 22 - .../tools/node_modules/ejs/examples/list.ejs | 7 - .../tools/node_modules/ejs/examples/list.js | 14 - .../html/tools/node_modules/ejs/index.js | 2 - .../html/tools/node_modules/ejs/lib/ejs.js | 357 ---------- .../tools/node_modules/ejs/lib/filters.js | 201 ------ .../html/tools/node_modules/ejs/lib/utils.js | 24 - .../html/tools/node_modules/ejs/package.json | 34 - .../tools/node_modules/ejs/support/compile.js | 177 ----- .../html/tools/node_modules/ejs/test/ejs.js | 306 --------- .../ejs/test/fixtures/backslash.ejs | 1 - .../ejs/test/fixtures/backslash.html | 1 - .../ejs/test/fixtures/comments.ejs | 5 - .../ejs/test/fixtures/comments.html | 4 - .../ejs/test/fixtures/double-quote.ejs | 1 - .../ejs/test/fixtures/double-quote.html | 1 - .../node_modules/ejs/test/fixtures/error.ejs | 5 - .../node_modules/ejs/test/fixtures/error.out | 8 - .../node_modules/ejs/test/fixtures/fail.ejs | 1 - .../ejs/test/fixtures/include.css.ejs | 1 - .../ejs/test/fixtures/include.css.html | 3 - .../ejs/test/fixtures/include.ejs | 5 - .../ejs/test/fixtures/include.html | 9 - .../ejs/test/fixtures/includes/menu-item.ejs | 1 - .../ejs/test/fixtures/includes/menu/item.ejs | 1 - .../node_modules/ejs/test/fixtures/menu.ejs | 11 - .../node_modules/ejs/test/fixtures/menu.html | 3 - .../node_modules/ejs/test/fixtures/messed.ejs | 1 - .../ejs/test/fixtures/messed.html | 1 - .../ejs/test/fixtures/newlines.ejs | 5 - .../ejs/test/fixtures/newlines.html | 9 - .../ejs/test/fixtures/no.newlines.ejs | 5 - .../ejs/test/fixtures/no.newlines.html | 5 - .../node_modules/ejs/test/fixtures/para.ejs | 1 - .../node_modules/ejs/test/fixtures/pet.ejs | 1 - .../ejs/test/fixtures/single-quote.ejs | 1 - .../ejs/test/fixtures/single-quote.html | 1 - .../node_modules/ejs/test/fixtures/style.css | 3 - .../node_modules/ejs/test/fixtures/user.ejs | 1 - .../tools/node_modules/eventproxy/.npmignore | 9 - .../tools/node_modules/eventproxy/MIT-License | 23 - .../tools/node_modules/eventproxy/README.md | 531 -------------- .../node_modules/eventproxy/README_en.md | 503 -------------- .../node_modules/eventproxy/component.json | 22 - .../tools/node_modules/eventproxy/index.js | 1 - .../node_modules/eventproxy/lib/eventproxy.js | 586 ---------------- .../eventproxy/node_modules/debug/.npmignore | 4 - .../eventproxy/node_modules/debug/History.md | 62 -- .../eventproxy/node_modules/debug/Readme.md | 115 ---- .../node_modules/debug/component.json | 9 - .../eventproxy/node_modules/debug/debug.js | 124 ---- .../node_modules/debug/example/app.js | 19 - .../node_modules/debug/example/browser.html | 24 - .../node_modules/debug/example/wildcards.js | 10 - .../node_modules/debug/example/worker.js | 22 - .../eventproxy/node_modules/debug/index.js | 5 - .../node_modules/debug/lib/debug.js | 134 ---- .../node_modules/debug/package.json | 41 -- .../node_modules/eventproxy/package.json | 69 -- disconf-web/html/tools/parse.js | 91 --- disconf-web/html/unitTpl/basefoot.html.tpl | 4 - disconf-web/html/unitTpl/basehead.html.tpl | 5 - disconf-web/html/unitTpl/foot.html.tpl | 36 - disconf-web/html/unitTpl/head.html.tpl | 82 --- disconf-web/html/unitTpl/leftbar.html.tpl | 11 - disconf-web/html/unitTpl/nav.html.tpl | 20 - .../profile/rd/application-demo.properties | 22 - .../profile/rd/redis-config.properties | 14 +- disconf-web/profile/rd/zoo.properties | 3 +- disconf-web/sql/201512/20151225.sql | 13 - disconf-web/sql/20160701/20160701.sql | 10 - disconf-web/sql/deprecated/.gitignore | 2 - disconf-web/sql/deprecated/1-init_table.sql | 56 -- disconf-web/sql/deprecated/2-data.sql | 24 - .../sql/deprecated/20141201/.gitignore | 1 - .../sql/deprecated/20141201/disconf.sql | 31 - .../sql/deprecated/20141226/.gitignore | 1 - .../sql/deprecated/20141226/disconf.sql | 147 ---- .../sql/deprecated/20150101/disconf.sql | 5 - .../sql/deprecated/20150320/disconf.sql | 6 - .../sql/deprecated/20150611/.gitignore | 1 - disconf-web/sql/deprecated/readme.txt | 12 - .../myconfig/applicationContext-cache.xml | 45 +- docs/image/DisconfMgrBean.png | Bin 0 -> 205780 bytes pom.xml | 36 +- sql/.gitignore | 2 - 126 files changed, 184 insertions(+), 6347 deletions(-) delete mode 100644 disconf-web/html/build.py delete mode 100644 disconf-web/html/build.sh delete mode 100644 disconf-web/html/mainTpl/index.tpl.html delete mode 100644 disconf-web/html/mainTpl/login.tpl.html delete mode 100644 disconf-web/html/mainTpl/main.tpl.html delete mode 100644 disconf-web/html/mainTpl/modifyFile.tpl.html delete mode 100644 disconf-web/html/mainTpl/modifyItem.tpl.html delete mode 100644 disconf-web/html/mainTpl/modifypassword.tpl.html delete mode 100644 disconf-web/html/mainTpl/newapp.tpl.html delete mode 100644 disconf-web/html/mainTpl/newconfig_file.tpl.html delete mode 100644 disconf-web/html/mainTpl/newconfig_item.tpl.html delete mode 100644 disconf-web/html/tools/gen_html.bat delete mode 100644 disconf-web/html/tools/gen_html.sh delete mode 100644 disconf-web/html/tools/node_modules/ejs/.gitmodules delete mode 100644 disconf-web/html/tools/node_modules/ejs/.npmignore delete mode 100644 disconf-web/html/tools/node_modules/ejs/.travis.yml delete mode 100644 disconf-web/html/tools/node_modules/ejs/History.md delete mode 100644 disconf-web/html/tools/node_modules/ejs/Makefile delete mode 100644 disconf-web/html/tools/node_modules/ejs/Readme.md delete mode 100644 disconf-web/html/tools/node_modules/ejs/benchmark.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/ejs.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/ejs.min.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/examples/client.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/examples/functions.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/examples/functions.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/examples/list.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/examples/list.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/index.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/lib/ejs.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/lib/filters.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/lib/utils.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/package.json delete mode 100644 disconf-web/html/tools/node_modules/ejs/support/compile.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/ejs.js delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/backslash.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/backslash.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/comments.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/comments.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/double-quote.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/double-quote.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/error.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/error.out delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/fail.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/include.css.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/include.css.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/include.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/include.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/includes/menu-item.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/includes/menu/item.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/menu.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/menu.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/messed.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/messed.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/newlines.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/newlines.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/no.newlines.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/no.newlines.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/para.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/pet.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/single-quote.ejs delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/single-quote.html delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/style.css delete mode 100644 disconf-web/html/tools/node_modules/ejs/test/fixtures/user.ejs delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/.npmignore delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/MIT-License delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/README.md delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/README_en.md delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/component.json delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/index.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/lib/eventproxy.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/.npmignore delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/History.md delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/Readme.md delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/component.json delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/debug.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/app.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/browser.html delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/wildcards.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/worker.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/index.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/lib/debug.js delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/package.json delete mode 100644 disconf-web/html/tools/node_modules/eventproxy/package.json delete mode 100644 disconf-web/html/tools/parse.js delete mode 100644 disconf-web/html/unitTpl/basefoot.html.tpl delete mode 100644 disconf-web/html/unitTpl/basehead.html.tpl delete mode 100644 disconf-web/html/unitTpl/foot.html.tpl delete mode 100644 disconf-web/html/unitTpl/head.html.tpl delete mode 100644 disconf-web/html/unitTpl/leftbar.html.tpl delete mode 100644 disconf-web/html/unitTpl/nav.html.tpl delete mode 100644 disconf-web/profile/rd/application-demo.properties delete mode 100644 disconf-web/sql/201512/20151225.sql delete mode 100644 disconf-web/sql/20160701/20160701.sql delete mode 100644 disconf-web/sql/deprecated/.gitignore delete mode 100644 disconf-web/sql/deprecated/1-init_table.sql delete mode 100644 disconf-web/sql/deprecated/2-data.sql delete mode 100644 disconf-web/sql/deprecated/20141201/.gitignore delete mode 100644 disconf-web/sql/deprecated/20141201/disconf.sql delete mode 100644 disconf-web/sql/deprecated/20141226/.gitignore delete mode 100644 disconf-web/sql/deprecated/20141226/disconf.sql delete mode 100644 disconf-web/sql/deprecated/20150101/disconf.sql delete mode 100644 disconf-web/sql/deprecated/20150320/disconf.sql delete mode 100644 disconf-web/sql/deprecated/20150611/.gitignore delete mode 100644 disconf-web/sql/deprecated/readme.txt create mode 100644 docs/image/DisconfMgrBean.png delete mode 100644 sql/.gitignore diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgr.java b/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgr.java index 9a6e51651..e24922c84 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgr.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgr.java @@ -53,7 +53,7 @@ private DisconfMgr() { } /** - * 总入口 + * 总入口 (Just for test ?) */ public synchronized void start(List scanPackageList) { @@ -199,6 +199,38 @@ public synchronized void reloadableScan(String fileName) { } } + /** + * reloadable config file scan, for xml config + * Modify at 20170802 by felix.sung + */ + public synchronized void reloadableScan(String fileName,String relativePath) { + + if (!isFirstInit) { + return; + } + + if (DisClientConfig.getInstance().ENABLE_DISCONF) { + try { + + if (!DisClientConfig.getInstance().getIgnoreDisconfKeySet().contains(fileName)) { + + if (scanMgr != null) { + scanMgr.reloadableScan(fileName,relativePath); + } + + if (disconfCoreMgr != null) { + disconfCoreMgr.processFile(fileName); + } + LOGGER.debug("disconf reloadable file: {} , relativeFilePath : {}", fileName , relativePath); + } + + } catch (Exception e) { + + LOGGER.error(e.toString(), e); + } + } + } + /** * @Description: 总关闭 */ diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgrBean.java b/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgrBean.java index 7c010fdbd..26a050627 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgrBean.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/DisconfMgrBean.java @@ -30,7 +30,7 @@ public class DisconfMgrBean implements BeanDefinitionRegistryPostProcessor, Prio private ApplicationContext applicationContext; - private String scanPackage = null; + private String scanPackage = null; public void destroy() { diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java b/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java index 939c72ee1..349485762 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Properties; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,14 +60,16 @@ public void setLocations(List fileNames) { filename = filename.trim(); String realFileName = getFileName(filename); + String relativeFilePath = getFileRelativePath(filename); // // register to disconf // - DisconfMgr.getInstance().reloadableScan(realFileName); + DisconfMgr.getInstance().reloadableScan(realFileName,relativeFilePath); // // only properties will reload + // TODO 是否可以考虑支持多类型配置文件 // String ext = FilenameUtils.getExtension(filename); if (ext.equals("properties")) { @@ -118,6 +121,29 @@ private String getFileName(String fileName) { return null; } + private String getFileRelativePath(String fileName){ + if (fileName != null) { + int index = fileName.indexOf(':'); + if (index < 0) { + } else { + fileName = fileName.substring(index + 1); + } + //配置文件应该使用相对路径,此操作避免读取系统绝对路径 + if(fileName.startsWith("/")){ + fileName = fileName.substring(1); + } + //判断是否包含目录 + if(fileName.indexOf("/") > 0){ + fileName = fileName.substring(0,fileName.lastIndexOf("/")); + }else{ + return ""; + } + + return fileName; + } + return null; + } + protected Resource[] getLocations() { return locations; } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/common/model/DisconfCenterFile.java b/disconf-client/src/main/java/com/baidu/disconf/client/common/model/DisconfCenterFile.java index 64d846bd6..6970ee869 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/common/model/DisconfCenterFile.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/common/model/DisconfCenterFile.java @@ -170,7 +170,7 @@ public String getFileDir() { if (targetDirPath.startsWith("/")) { return OsUtil.pathJoin(targetDirPath); } - + LOGGER.info("Download target file path : {}" , OsUtil.pathJoin(ClassLoaderUtil.getClassPath(), targetDirPath)); return OsUtil.pathJoin(ClassLoaderUtil.getClassPath(), targetDirPath); } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/scan/ScanMgr.java b/disconf-client/src/main/java/com/baidu/disconf/client/scan/ScanMgr.java index 832ad6720..2ef6a7e9d 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/scan/ScanMgr.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/scan/ScanMgr.java @@ -24,4 +24,12 @@ public interface ScanMgr { * @throws Exception */ void reloadableScan(String fileName) throws Exception; + + /** + * reloadable for non-annotation config file(eg: spring xml) + * @param fileName config file name + * @param relativePath relative path + * @throws Exception + */ + void reloadableScan(String fileName , String relativePath) throws Exception; } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/scan/impl/ScanMgrImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/scan/impl/ScanMgrImpl.java index 0d7c238ac..4f93c3b25 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/scan/impl/ScanMgrImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/scan/impl/ScanMgrImpl.java @@ -114,4 +114,9 @@ public void reloadableScan(String fileName) throws Exception { StaticScannerNonAnnotationFileMgrImpl.scanData2Store(fileName); } + @Override + public void reloadableScan(String fileName, String relativePath) throws Exception { + StaticScannerNonAnnotationFileMgrImpl.scanData2Store(fileName,relativePath); + } + } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/scan/inner/statically/impl/StaticScannerNonAnnotationFileMgrImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/scan/inner/statically/impl/StaticScannerNonAnnotationFileMgrImpl.java index cb6e5914e..cd934ee2e 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/scan/inner/statically/impl/StaticScannerNonAnnotationFileMgrImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/scan/inner/statically/impl/StaticScannerNonAnnotationFileMgrImpl.java @@ -37,6 +37,7 @@ public void scanData2Store(ScanStaticModel scanModel) { /** * */ + @Deprecated public static void scanData2Store(String fileName) { DisconfCenterBaseModel disconfCenterBaseModel = @@ -45,6 +46,14 @@ public static void scanData2Store(String fileName) { DisconfStoreProcessorFactory.getDisconfStoreFileProcessor().transformScanData(disconfCenterBaseModel); } + public static void scanData2Store(String fileName, String relativePath) { + + DisconfCenterBaseModel disconfCenterBaseModel = + StaticScannerNonAnnotationFileMgrImpl.getDisconfCenterFile(fileName,relativePath); + + DisconfStoreProcessorFactory.getDisconfStoreFileProcessor().transformScanData(disconfCenterBaseModel); + } + /** * */ @@ -104,4 +113,41 @@ public static DisconfCenterBaseModel getDisconfCenterFile(String fileName) { return disconfCenterFile; } + /** + * + */ + public static DisconfCenterBaseModel getDisconfCenterFile(String fileName , String relativePath) { + + DisconfCenterFile disconfCenterFile = new DisconfCenterFile(); + + fileName = fileName.trim(); + + // + // file name + disconfCenterFile.setFileName(fileName); + + // 非注解式 + disconfCenterFile.setIsTaggedWithNonAnnotationFile(true); + + // file type + disconfCenterFile.setSupportFileTypeEnum(SupportFileTypeEnum.getByFileName(fileName)); + disconfCenterFile.setTargetDirPath(relativePath); + + // + // disConfCommonModel + DisConfCommonModel disConfCommonModel = makeDisConfCommonModel("", "", ""); + disconfCenterFile.setDisConfCommonModel(disConfCommonModel); + + // Remote URL + String url = DisconfWebPathMgr.getRemoteUrlParameter(DisClientSysConfig.getInstance().CONF_SERVER_STORE_ACTION, + disConfCommonModel.getApp(), + disConfCommonModel.getVersion(), + disConfCommonModel.getEnv(), + disconfCenterFile.getFileName(), + DisConfigTypeEnum.FILE); + disconfCenterFile.setRemoteServerUrl(url); + + return disconfCenterFile; + } + } diff --git a/disconf-web/html/build.py b/disconf-web/html/build.py deleted file mode 100644 index 4c9860336..000000000 --- a/disconf-web/html/build.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python -# coding=utf8 - -import os -import shutil - -import sys - - -reload(sys) -sys.setdefaultencoding('utf-8') # @UndefinedVariable - -# 输出文件夹 -OUT_DIR = "output" - - -# -# 删除目录 (递归) -# -# Delete everything reachable from the directory named in "top", -# assuming there are no symbolic links. -# CAUTION: This is dangerous! For example, if top == '/', it -# could delete all your disk files. -def rmdir(top): - import os - - for root, dirs, files in os.walk(top, topdown=False): - for name in files: - os.remove(os.path.join(root, name)) - for name in dirs: - os.rmdir(os.path.join(root, name)) - - -# -# 复制目录(递归) -# assets -> output/assets -# dep -> output/dep -# -def copytree(src_dir, dest_dir, symlinks=False, ignore=None): - for item in os.listdir(src_dir): - s = os.path.join(src_dir, item) - d = os.path.join(dest_dir, item) - if os.path.isdir(s): - shutil.copytree(s, d, symlinks, ignore) - else: - shutil.copy2(s, d) - - -# -# 复制类ShellPattern的文件至目录 (非递归) -# -def copyFilePattern(src_dir, dest_dir, pattern): - import glob - - files = glob.iglob(os.path.join(src_dir, pattern)) - for file in files: - if os.path.isfile(file): - shutil.copy(file, dest_dir) - - -# -# 入口 -# -if __name__ == '__main__': - - try: - - # 删除输出文件夹 - rmdir(OUT_DIR) - - # - if not os.path.exists(OUT_DIR): - os.makedirs(OUT_DIR) - - # - copytree("assets", OUT_DIR + "/assets") - copytree("dep", OUT_DIR + "/dep") - copyFilePattern(".", OUT_DIR, "*.html") - - except KeyboardInterrupt: - pass - - - diff --git a/disconf-web/html/build.sh b/disconf-web/html/build.sh deleted file mode 100644 index 114701234..000000000 --- a/disconf-web/html/build.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -cd "${0%/*}" - -# -# 打包FE包 -# - -# -if [ -d "output" ]; then - printf '%s\n' "Removing output" - rm -rf output -fi - -mkdir -p output - -cp -rp assets output -cp -rp dep output -cp -rp *.html output diff --git a/disconf-web/html/index.html b/disconf-web/html/index.html index 6c0832c66..bf3cd0be5 100644 --- a/disconf-web/html/index.html +++ b/disconf-web/html/index.html @@ -107,18 +107,7 @@ @@ -129,16 +118,6 @@ - - diff --git a/disconf-web/html/login.html b/disconf-web/html/login.html index 872703a24..bc0db6494 100644 --- a/disconf-web/html/login.html +++ b/disconf-web/html/login.html @@ -138,18 +138,7 @@

登录

@@ -160,17 +149,6 @@

登录

- - - diff --git a/disconf-web/html/main.html b/disconf-web/html/main.html index d057addf8..b5488f004 100644 --- a/disconf-web/html/main.html +++ b/disconf-web/html/main.html @@ -185,18 +185,7 @@ @@ -207,17 +196,6 @@ - - - diff --git a/disconf-web/html/mainTpl/index.tpl.html b/disconf-web/html/mainTpl/index.tpl.html deleted file mode 100644 index c9eabfa85..000000000 --- a/disconf-web/html/mainTpl/index.tpl.html +++ /dev/null @@ -1,24 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
-
-
- -
-
- -
-
-
-
-
- -<%= page.foot %> - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/login.tpl.html b/disconf-web/html/mainTpl/login.tpl.html deleted file mode 100644 index a33552fe2..000000000 --- a/disconf-web/html/mainTpl/login.tpl.html +++ /dev/null @@ -1,55 +0,0 @@ -<%= page.basehead %> - -Disconf - 登录到分布式配置管理平台 - -<%= page.head %> - -
-
-
- -
-
- -

登录

- - - -
- - -
- - - - - -
-
    -
  • - -
  • -
- -
-
- -
-
-
- -<%= page.foot %> - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/main.tpl.html b/disconf-web/html/mainTpl/main.tpl.html deleted file mode 100644 index 6b73fab33..000000000 --- a/disconf-web/html/mainTpl/main.tpl.html +++ /dev/null @@ -1,91 +0,0 @@ -<%= page.basehead %> -Disconf - 分布式配置管理平台 -<%= page.head %> - -
-
-
-
- -
- -
-
- -
-
- - - -
-
-                                
-
- -
- -
- - - - - - - - - - - - - - - -
-
-
- - -
- - - - - - - - - - -
{12}{1}{6}   {5}{14}{15}{8}{10}   {11}   {13}  
-
- -
-
-
-
- -<%= page.foot %> - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/modifyFile.tpl.html b/disconf-web/html/mainTpl/modifyFile.tpl.html deleted file mode 100644 index 19d1f4518..000000000 --- a/disconf-web/html/mainTpl/modifyFile.tpl.html +++ /dev/null @@ -1,155 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
-
-
- -
- -
- -
- -
- - -
- -
- -
- -
-

配置文件修改

- -

- APP id & 名称: - FFFF -

- -

- 版本: - FFFF -

- -

- 环境: - FFFF -

- -

- 配置文件名: - FFFF -

- -
- 原配置文件内容: -
FFFF
-
- -
- 修改方式: - - -
- -
- 上传配置文件: - -
- -
- 上传配置文件... -
- -
-
- - -
- 仅支持任意类型配置文件(.properties文件可支持自动注入, 非.properties文件则只是简单托管) - -
-
-
-
- 0% -
-
-
-
-
- -
- -
- 输入文本: - -
- -
- -
- 表单选项不能为空或填写格式错误! -
- -
- -
- -
- -
-
-
-
-
-
- - -
-
  • - {0} -
  • -
    - -<%= page.foot %> - - - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/modifyItem.tpl.html b/disconf-web/html/mainTpl/modifyItem.tpl.html deleted file mode 100644 index 70c0176d4..000000000 --- a/disconf-web/html/mainTpl/modifyItem.tpl.html +++ /dev/null @@ -1,95 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
    -
    -
    - -
    - -
    - -
    - -
    - - -
    - -
    - -
    - -
    -

    配置项修改

    - -

    - APP id & 名称: - FFFF -

    - -

    - 版本: - FFFF -

    - -

    - 环境: - FFFF -

    - -

    - 配置KEY: - FFFF -

    - -

    - 配置值: - -

    - - -
    - -
    - -
    -
    -
    -
    -
    -
    -
    - - -
    -
  • - {0} -
  • -
    - -<%= page.foot %> - - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/modifypassword.tpl.html b/disconf-web/html/mainTpl/modifypassword.tpl.html deleted file mode 100644 index 4d13b3fcc..000000000 --- a/disconf-web/html/mainTpl/modifypassword.tpl.html +++ /dev/null @@ -1,64 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
    -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    -

    修改密码

    - -
    - 原密码: - -
    - -
    - 新密码: - -
    - -
    - 新密码(重复): - -
    - - - -
    -
    -
    -
    -
    -
    -
    - -<%= page.foot %> - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/newapp.tpl.html b/disconf-web/html/mainTpl/newapp.tpl.html deleted file mode 100644 index 4c12a9a0c..000000000 --- a/disconf-web/html/mainTpl/newapp.tpl.html +++ /dev/null @@ -1,66 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
    -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    -

    新建APP

    - -
    - APP: - -
    - -
    - 说明: - -
    - -
    - Emails(;号分隔): - -
    - - - -
    -
    -
    -
    -
    -
    -
    - -<%= page.foot %> - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/newconfig_file.tpl.html b/disconf-web/html/mainTpl/newconfig_file.tpl.html deleted file mode 100644 index b27b4d40b..000000000 --- a/disconf-web/html/mainTpl/newconfig_file.tpl.html +++ /dev/null @@ -1,150 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
    -
    -
    - -
    - -
    - -
    - -
    - -
    - -
    -

    新建配置文件

    - -
    - APP选择: - - -
    -
    - 版本: - - -
    - -
    - 环境: - - -
    - -
    - 上传方式: - - -
    - - -
    - 上传配置文件: - -
    - -
    - 上传配置文件... -
    - -
    - - -
    - 支持任意类型配置文件(.properties文件可支持自动注入,非.properties文件则只是简单托管) - -
    -
    -
    -
    - 0% -
    -
    -
    -
    -
    - -
    - -
    - 文件名: - -
    - -
    - 输入文本: - -
    - -
    - -
    - 表单选项不能为空或填写格式错误! -
    - -
    - -
    - -
    -
    -
    -
    -
    -
    -
    - -<%= page.foot %> - - - - - -<%= page.basefoot %> diff --git a/disconf-web/html/mainTpl/newconfig_item.tpl.html b/disconf-web/html/mainTpl/newconfig_item.tpl.html deleted file mode 100644 index 5868c3973..000000000 --- a/disconf-web/html/mainTpl/newconfig_item.tpl.html +++ /dev/null @@ -1,91 +0,0 @@ -<%= page.basehead %> - -Disconf - 分布式配置管理平台 - -<%= page.head %> - -
    -
    -
    - -
    - -
    - -
    -
    - -
    -
    -

    新建配置项

    - -
    - APP选择: - - -
    -
    - 版本: - - -
    - -
    - 环境: - - -
    -
    - 配置项名: - -
    -
    - 配置值: - -
    - - - -
    -
    - -
    -
    -
    -
    -
    - -<%= page.foot %> - - - - -<%= page.basefoot %> diff --git a/disconf-web/html/modifyFile.html b/disconf-web/html/modifyFile.html index a4c6104ae..f800374e7 100644 --- a/disconf-web/html/modifyFile.html +++ b/disconf-web/html/modifyFile.html @@ -236,18 +236,7 @@

    配置文件修改

    @@ -258,17 +247,6 @@

    配置文件修改

    - - - diff --git a/disconf-web/html/modifyItem.html b/disconf-web/html/modifyItem.html index 6b1fb7757..8153e9344 100644 --- a/disconf-web/html/modifyItem.html +++ b/disconf-web/html/modifyItem.html @@ -177,18 +177,7 @@

    配置项修改

    @@ -199,17 +188,6 @@

    配置项修改

    - - - diff --git a/disconf-web/html/modifypassword.html b/disconf-web/html/modifypassword.html index 67144e9e6..7a5f398be 100644 --- a/disconf-web/html/modifypassword.html +++ b/disconf-web/html/modifypassword.html @@ -147,18 +147,7 @@

    修改密码

    @@ -169,17 +158,6 @@

    修改密码

    - - - diff --git a/disconf-web/html/newapp.html b/disconf-web/html/newapp.html index 5c4f6ef93..4bf5f4811 100644 --- a/disconf-web/html/newapp.html +++ b/disconf-web/html/newapp.html @@ -149,18 +149,7 @@

    新建APP

    @@ -171,17 +160,6 @@

    新建APP

    - - - diff --git a/disconf-web/html/newconfig_file.html b/disconf-web/html/newconfig_file.html index 3d0ab80a7..c43a692d0 100644 --- a/disconf-web/html/newconfig_file.html +++ b/disconf-web/html/newconfig_file.html @@ -231,18 +231,7 @@

    新建配置文件

    @@ -253,17 +242,6 @@

    新建配置文件

    - - - diff --git a/disconf-web/html/newconfig_item.html b/disconf-web/html/newconfig_item.html index ae71de74f..9e4a6c04e 100644 --- a/disconf-web/html/newconfig_item.html +++ b/disconf-web/html/newconfig_item.html @@ -173,18 +173,7 @@

    新建配置项

    @@ -195,18 +184,6 @@

    新建配置项

    - - - - diff --git a/disconf-web/html/tools/gen_html.bat b/disconf-web/html/tools/gen_html.bat deleted file mode 100644 index 32dc669a5..000000000 --- a/disconf-web/html/tools/gen_html.bat +++ /dev/null @@ -1,7 +0,0 @@ - - -echo %~dp0 - -cd %~dp0 - -node parse.js diff --git a/disconf-web/html/tools/gen_html.sh b/disconf-web/html/tools/gen_html.sh deleted file mode 100644 index a4e56e534..000000000 --- a/disconf-web/html/tools/gen_html.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -node parse.js \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/.gitmodules b/disconf-web/html/tools/node_modules/ejs/.gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/disconf-web/html/tools/node_modules/ejs/.npmignore b/disconf-web/html/tools/node_modules/ejs/.npmignore deleted file mode 100644 index 020ddac2c..000000000 --- a/disconf-web/html/tools/node_modules/ejs/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -# ignore any vim files: -*.sw[a-z] -vim/.netrwhist -node_modules diff --git a/disconf-web/html/tools/node_modules/ejs/.travis.yml b/disconf-web/html/tools/node_modules/ejs/.travis.yml deleted file mode 100644 index 1ccd29932..000000000 --- a/disconf-web/html/tools/node_modules/ejs/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - 0.11 - - 0.10 - - 0.9 - - 0.6 - - 0.8 diff --git a/disconf-web/html/tools/node_modules/ejs/History.md b/disconf-web/html/tools/node_modules/ejs/History.md deleted file mode 100644 index df3ccf608..000000000 --- a/disconf-web/html/tools/node_modules/ejs/History.md +++ /dev/null @@ -1,138 +0,0 @@ - -0.8.5 / 2013-11-21 -================== - - * fix: Escape apostrophe & don't over-match existing entities - * fix function name changed by uglify - * fixes require, closes #78 - -0.8.4 / 2013-05-08 -================== - - * fix support for colons in filter arguments - * fix double callback when the callback throws - * rename escape option - -0.8.3 / 2012-09-13 -================== - - * allow pre-compiling into a standalone function [seanmonstar] - -0.8.2 / 2012-08-16 -================== - - * fix include "open" / "close" options. Closes #64 - -0.8.1 / 2012-08-11 -================== - - * fix comments. Closes #62 [Nate Silva] - -0.8.0 / 2012-07-25 -================== - - * add `<% include file %>` support - * fix wrapping of custom require in build step. Closes #57 - -0.7.3 / 2012-04-25 -================== - - * Added repository to package.json [isaacs] - -0.7.1 / 2012-03-26 -================== - - * Fixed exception when using express in production caused by typo. [slaskis] - -0.7.0 / 2012-03-24 -================== - - * Added newline consumption support (`-%>`) [whoatemydomain] - -0.6.1 / 2011-12-09 -================== - - * Fixed `ejs.renderFile()` - -0.6.0 / 2011-12-09 -================== - - * Changed: you no longer need `{ locals: {} }` - -0.5.0 / 2011-11-20 -================== - - * Added express 3.x support - * Added ejs.renderFile() - * Added 'json' filter - * Fixed tests for 0.5.x - -0.4.3 / 2011-06-20 -================== - - * Fixed stacktraces line number when used multiline js expressions [Octave] - -0.4.2 / 2011-05-11 -================== - - * Added client side support - -0.4.1 / 2011-04-21 -================== - - * Fixed error context - -0.4.0 / 2011-04-21 -================== - - * Added; ported jade's error reporting to ejs. [slaskis] - -0.3.1 / 2011-02-23 -================== - - * Fixed optional `compile()` options - -0.3.0 / 2011-02-14 -================== - - * Added 'json' filter [Yuriy Bogdanov] - * Use exported version of parse function to allow monkey-patching [Anatoliy Chakkaev] - -0.2.1 / 2010-10-07 -================== - - * Added filter support - * Fixed _cache_ option. ~4x performance increase - -0.2.0 / 2010-08-05 -================== - - * Added support for global tag config - * Added custom tag support. Closes #5 - * Fixed whitespace bug. Closes #4 - -0.1.0 / 2010-08-04 -================== - - * Faster implementation [ashleydev] - -0.0.4 / 2010-08-02 -================== - - * Fixed single quotes for content outside of template tags. [aniero] - * Changed; `exports.compile()` now expects only "locals" - -0.0.3 / 2010-07-15 -================== - - * Fixed single quotes - -0.0.2 / 2010-07-09 -================== - - * Fixed newline preservation - -0.0.1 / 2010-07-09 -================== - - * Initial release diff --git a/disconf-web/html/tools/node_modules/ejs/Makefile b/disconf-web/html/tools/node_modules/ejs/Makefile deleted file mode 100644 index a687a0a52..000000000 --- a/disconf-web/html/tools/node_modules/ejs/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -SRC = $(shell find lib -name "*.js" -type f) -UGLIFY_FLAGS = --no-mangle - -all: ejs.min.js - -test: - @./node_modules/.bin/mocha \ - --reporter spec - -ejs.js: $(SRC) - @node support/compile.js $^ - -ejs.min.js: ejs.js - @uglifyjs $(UGLIFY_FLAGS) $< > $@ \ - && du ejs.min.js \ - && du ejs.js - -clean: - rm -f ejs.js - rm -f ejs.min.js - -.PHONY: test \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/Readme.md b/disconf-web/html/tools/node_modules/ejs/Readme.md deleted file mode 100644 index ab0a3dd14..000000000 --- a/disconf-web/html/tools/node_modules/ejs/Readme.md +++ /dev/null @@ -1,188 +0,0 @@ -# EJS - -Embedded JavaScript templates. - -[![Build Status](https://travis-ci.org/visionmedia/ejs.png)](https://travis-ci.org/visionmedia/ejs) - -## Installation - - $ npm install ejs - -## Features - - * Complies with the [Express](http://expressjs.com) view system - * Static caching of intermediate JavaScript - * Unbuffered code for conditionals etc `<% code %>` - * Escapes html by default with `<%= code %>` - * Unescaped buffering with `<%- code %>` - * Supports tag customization - * Filter support for designer-friendly templates - * Includes - * Client-side support - * Newline slurping with `<% code -%>` or `<% -%>` or `<%= code -%>` or `<%- code -%>` - -## Example - - <% if (user) { %> -

    <%= user.name %>

    - <% } %> - -## Try out a live example now - - - -## Usage - - ejs.compile(str, options); - // => Function - - ejs.render(str, options); - // => str - -## Options - - - `cache` Compiled functions are cached, requires `filename` - - `filename` Used by `cache` to key caches - - `scope` Function execution context - - `debug` Output generated function body - - `compileDebug` When `false` no debug instrumentation is compiled - - `client` Returns standalone compiled function - - `open` Open tag, defaulting to "<%" - - `close` Closing tag, defaulting to "%>" - - * All others are template-local variables - -## Includes - - Includes are relative to the template with the `include` statement, - for example if you have "./views/users.ejs" and "./views/user/show.ejs" - you would use `<% include user/show %>`. The included file(s) are literally - included into the template, _no_ IO is performed after compilation, thus - local variables are available to these included templates. - -``` -
      - <% users.forEach(function(user){ %> - <% include user/show %> - <% }) %> -
    -``` - -## Custom delimiters - -Custom delimiters can also be applied globally: - - var ejs = require('ejs'); - ejs.open = '{{'; - ejs.close = '}}'; - -Which would make the following a valid template: - -

    {{= title }}

    - -## Filters - -EJS conditionally supports the concept of "filters". A "filter chain" -is a designer friendly api for manipulating data, without writing JavaScript. - -Filters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters: - -Template: - -

    <%=: users | map:'name' | join %>

    - -Output: - -

    Tj, Mape, Guillermo

    - -Render call: - - ejs.render(str, { - users: [ - { name: 'tj' }, - { name: 'mape' }, - { name: 'guillermo' } - ] - }); - -Or perhaps capitalize the first user's name for display: - -

    <%=: users | first | capitalize %>

    - -## Filter list - -Currently these filters are available: - - - first - - last - - capitalize - - downcase - - upcase - - sort - - sort_by:'prop' - - size - - length - - plus:n - - minus:n - - times:n - - divided_by:n - - join:'val' - - truncate:n - - truncate_words:n - - replace:pattern,substitution - - prepend:val - - append:val - - map:'prop' - - reverse - - get:'prop' - -## Adding filters - - To add a filter simply add a method to the `.filters` object: - -```js -ejs.filters.last = function(obj) { - return obj[obj.length - 1]; -}; -``` - -## Layouts - - Currently EJS has no notion of blocks, only compile-time `include`s, - however you may still utilize this feature to implement "layouts" by - simply including a header and footer like so: - -```html -<% include head %> -

    Title

    -

    My page

    -<% include foot %> -``` - -## client-side support - - include `./ejs.js` or `./ejs.min.js` and `require("ejs").compile(str)`. - -## License - -(The MIT License) - -Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca> - -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. diff --git a/disconf-web/html/tools/node_modules/ejs/benchmark.js b/disconf-web/html/tools/node_modules/ejs/benchmark.js deleted file mode 100644 index 7b267e160..000000000 --- a/disconf-web/html/tools/node_modules/ejs/benchmark.js +++ /dev/null @@ -1,14 +0,0 @@ - - -var ejs = require('./lib/ejs'), - str = '<% if (foo) { %>

    <%= foo %>

    <% } %>', - times = 50000; - -console.log('rendering ' + times + ' times'); - -var start = new Date; -while (times--) { - ejs.render(str, { cache: true, filename: 'test', locals: { foo: 'bar' }}); -} - -console.log('took ' + (new Date - start) + 'ms'); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/ejs.js b/disconf-web/html/tools/node_modules/ejs/ejs.js deleted file mode 100644 index ab44a80c3..000000000 --- a/disconf-web/html/tools/node_modules/ejs/ejs.js +++ /dev/null @@ -1,647 +0,0 @@ -ejs = (function(){ - -// CommonJS require() - -function require(p){ - if ('fs' == p) return {}; - if ('path' == p) return {}; - var path = require.resolve(p) - , mod = require.modules[path]; - if (!mod) throw new Error('failed to require "' + p + '"'); - if (!mod.exports) { - mod.exports = {}; - mod.call(mod.exports, mod, mod.exports, require.relative(path)); - } - return mod.exports; - } - -require.modules = {}; - -require.resolve = function (path){ - var orig = path - , reg = path + '.js' - , index = path + '/index.js'; - return require.modules[reg] && reg - || require.modules[index] && index - || orig; - }; - -require.register = function (path, fn){ - require.modules[path] = fn; - }; - -require.relative = function (parent) { - return function(p){ - if ('.' != p.substr(0, 1)) return require(p); - - var path = parent.split('/') - , segs = p.split('/'); - path.pop(); - - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - if ('..' == seg) path.pop(); - else if ('.' != seg) path.push(seg); - } - - return require(path.join('/')); - }; - }; - - -require.register("ejs.js", function(module, exports, require){ - -/*! - * EJS - * Copyright(c) 2012 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Module dependencies. - */ - -var utils = require('./utils') - , path = require('path') - , dirname = path.dirname - , extname = path.extname - , join = path.join - , fs = require('fs') - , read = fs.readFileSync; - -/** - * Filters. - * - * @type Object - */ - -var filters = exports.filters = require('./filters'); - -/** - * Intermediate js cache. - * - * @type Object - */ - -var cache = {}; - -/** - * Clear intermediate js cache. - * - * @api public - */ - -exports.clearCache = function(){ - cache = {}; -}; - -/** - * Translate filtered code into function calls. - * - * @param {String} js - * @return {String} - * @api private - */ - -function filtered(js) { - return js.substr(1).split('|').reduce(function(js, filter){ - var parts = filter.split(':') - , name = parts.shift() - , args = parts.join(':') || ''; - if (args) args = ', ' + args; - return 'filters.' + name + '(' + js + args + ')'; - }); -}; - -/** - * Re-throw the given `err` in context to the - * `str` of ejs, `filename`, and `lineno`. - * - * @param {Error} err - * @param {String} str - * @param {String} filename - * @param {String} lineno - * @api private - */ - -function rethrow(err, str, filename, lineno){ - var lines = str.split('\n') - , start = Math.max(lineno - 3, 0) - , end = Math.min(lines.length, lineno + 3); - - // Error context - var context = lines.slice(start, end).map(function(line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; -} - -/** - * Parse the given `str` of ejs, returning the function body. - * - * @param {String} str - * @return {String} - * @api public - */ - -var parse = exports.parse = function(str, options){ - var options = options || {} - , open = options.open || exports.open || '<%' - , close = options.close || exports.close || '%>' - , filename = options.filename - , compileDebug = options.compileDebug !== false - , buf = ""; - - buf += 'var buf = [];'; - if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ '; - buf += '\n buf.push(\''; - - var lineno = 1; - - var consumeEOL = false; - for (var i = 0, len = str.length; i < len; ++i) { - var stri = str[i]; - if (str.slice(i, open.length + i) == open) { - i += open.length - - var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno; - switch (str[i]) { - case '=': - prefix = "', escape((" + line + ', '; - postfix = ")), '"; - ++i; - break; - case '-': - prefix = "', (" + line + ', '; - postfix = "), '"; - ++i; - break; - default: - prefix = "');" + line + ';'; - postfix = "; buf.push('"; - } - - var end = str.indexOf(close, i) - , js = str.substring(i, end) - , start = i - , include = null - , n = 0; - - if ('-' == js[js.length-1]){ - js = js.substring(0, js.length - 2); - consumeEOL = true; - } - - if (0 == js.trim().indexOf('include')) { - var name = js.trim().slice(7).trim(); - if (!filename) throw new Error('filename option is required for includes'); - var path = resolveInclude(name, filename); - include = read(path, 'utf8'); - include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug }); - buf += "' + (function(){" + include + "})() + '"; - js = ''; - } - - while (~(n = js.indexOf("\n", n))) n++, lineno++; - if (js.substr(0, 1) == ':') js = filtered(js); - if (js) { - if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n'; - buf += prefix; - buf += js; - buf += postfix; - } - i += end - start + close.length - 1; - - } else if (stri == "\\") { - buf += "\\\\"; - } else if (stri == "'") { - buf += "\\'"; - } else if (stri == "\r") { - // ignore - } else if (stri == "\n") { - if (consumeEOL) { - consumeEOL = false; - } else { - buf += "\\n"; - lineno++; - } - } else { - buf += stri; - } - } - - if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');"; - else buf += "');\nreturn buf.join('');"; - return buf; -}; - -/** - * Compile the given `str` of ejs into a `Function`. - * - * @param {String} str - * @param {Object} options - * @return {Function} - * @api public - */ - -var compile = exports.compile = function(str, options){ - options = options || {}; - var escape = options.escape || utils.escape; - - var input = JSON.stringify(str) - , compileDebug = options.compileDebug !== false - , client = options.client - , filename = options.filename - ? JSON.stringify(options.filename) - : 'undefined'; - - if (compileDebug) { - // Adds the fancy stack trace meta info - str = [ - 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', - rethrow.toString(), - 'try {', - exports.parse(str, options), - '} catch (err) {', - ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', - '}' - ].join("\n"); - } else { - str = exports.parse(str, options); - } - - if (options.debug) console.log(str); - if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str; - - try { - var fn = new Function('locals, filters, escape, rethrow', str); - } catch (err) { - if ('SyntaxError' == err.name) { - err.message += options.filename - ? ' in ' + filename - : ' while compiling ejs'; - } - throw err; - } - - if (client) return fn; - - return function(locals){ - return fn.call(this, locals, filters, escape, rethrow); - } -}; - -/** - * Render the given `str` of ejs. - * - * Options: - * - * - `locals` Local variables object - * - `cache` Compiled functions are cached, requires `filename` - * - `filename` Used by `cache` to key caches - * - `scope` Function execution context - * - `debug` Output generated function body - * - `open` Open tag, defaulting to "<%" - * - `close` Closing tag, defaulting to "%>" - * - * @param {String} str - * @param {Object} options - * @return {String} - * @api public - */ - -exports.render = function(str, options){ - var fn - , options = options || {}; - - if (options.cache) { - if (options.filename) { - fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); - } else { - throw new Error('"cache" option requires "filename".'); - } - } else { - fn = compile(str, options); - } - - options.__proto__ = options.locals; - return fn.call(options.scope, options); -}; - -/** - * Render an EJS file at the given `path` and callback `fn(err, str)`. - * - * @param {String} path - * @param {Object|Function} options or callback - * @param {Function} fn - * @api public - */ - -exports.renderFile = function(path, options, fn){ - var key = path + ':string'; - - if ('function' == typeof options) { - fn = options, options = {}; - } - - options.filename = path; - - var str; - try { - str = options.cache - ? cache[key] || (cache[key] = read(path, 'utf8')) - : read(path, 'utf8'); - } catch (err) { - fn(err); - return; - } - fn(null, exports.render(str, options)); -}; - -/** - * Resolve include `name` relative to `filename`. - * - * @param {String} name - * @param {String} filename - * @return {String} - * @api private - */ - -function resolveInclude(name, filename) { - var path = join(dirname(filename), name); - var ext = extname(name); - if (!ext) path += '.ejs'; - return path; -} - -// express support - -exports.__express = exports.renderFile; - -/** - * Expose to require(). - */ - -if (require.extensions) { - require.extensions['.ejs'] = function (module, filename) { - filename = filename || module.filename; - var options = { filename: filename, client: true } - , template = fs.readFileSync(filename).toString() - , fn = compile(template, options); - module._compile('module.exports = ' + fn.toString() + ';', filename); - }; -} else if (require.registerExtension) { - require.registerExtension('.ejs', function(src) { - return compile(src, {}); - }); -} - -}); // module: ejs.js - -require.register("filters.js", function(module, exports, require){ -/*! - * EJS - Filters - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * First element of the target `obj`. - */ - -exports.first = function(obj) { - return obj[0]; -}; - -/** - * Last element of the target `obj`. - */ - -exports.last = function(obj) { - return obj[obj.length - 1]; -}; - -/** - * Capitalize the first letter of the target `str`. - */ - -exports.capitalize = function(str){ - str = String(str); - return str[0].toUpperCase() + str.substr(1, str.length); -}; - -/** - * Downcase the target `str`. - */ - -exports.downcase = function(str){ - return String(str).toLowerCase(); -}; - -/** - * Uppercase the target `str`. - */ - -exports.upcase = function(str){ - return String(str).toUpperCase(); -}; - -/** - * Sort the target `obj`. - */ - -exports.sort = function(obj){ - return Object.create(obj).sort(); -}; - -/** - * Sort the target `obj` by the given `prop` ascending. - */ - -exports.sort_by = function(obj, prop){ - return Object.create(obj).sort(function(a, b){ - a = a[prop], b = b[prop]; - if (a > b) return 1; - if (a < b) return -1; - return 0; - }); -}; - -/** - * Size or length of the target `obj`. - */ - -exports.size = exports.length = function(obj) { - return obj.length; -}; - -/** - * Add `a` and `b`. - */ - -exports.plus = function(a, b){ - return Number(a) + Number(b); -}; - -/** - * Subtract `b` from `a`. - */ - -exports.minus = function(a, b){ - return Number(a) - Number(b); -}; - -/** - * Multiply `a` by `b`. - */ - -exports.times = function(a, b){ - return Number(a) * Number(b); -}; - -/** - * Divide `a` by `b`. - */ - -exports.divided_by = function(a, b){ - return Number(a) / Number(b); -}; - -/** - * Join `obj` with the given `str`. - */ - -exports.join = function(obj, str){ - return obj.join(str || ', '); -}; - -/** - * Truncate `str` to `len`. - */ - -exports.truncate = function(str, len, append){ - str = String(str); - if (str.length > len) { - str = str.slice(0, len); - if (append) str += append; - } - return str; -}; - -/** - * Truncate `str` to `n` words. - */ - -exports.truncate_words = function(str, n){ - var str = String(str) - , words = str.split(/ +/); - return words.slice(0, n).join(' '); -}; - -/** - * Replace `pattern` with `substitution` in `str`. - */ - -exports.replace = function(str, pattern, substitution){ - return String(str).replace(pattern, substitution || ''); -}; - -/** - * Prepend `val` to `obj`. - */ - -exports.prepend = function(obj, val){ - return Array.isArray(obj) - ? [val].concat(obj) - : val + obj; -}; - -/** - * Append `val` to `obj`. - */ - -exports.append = function(obj, val){ - return Array.isArray(obj) - ? obj.concat(val) - : obj + val; -}; - -/** - * Map the given `prop`. - */ - -exports.map = function(arr, prop){ - return arr.map(function(obj){ - return obj[prop]; - }); -}; - -/** - * Reverse the given `obj`. - */ - -exports.reverse = function(obj){ - return Array.isArray(obj) - ? obj.reverse() - : String(obj).split('').reverse().join(''); -}; - -/** - * Get `prop` of the given `obj`. - */ - -exports.get = function(obj, prop){ - return obj[prop]; -}; - -/** - * Packs the given `obj` into json string - */ -exports.json = function(obj){ - return JSON.stringify(obj); -}; - -}); // module: filters.js - -require.register("utils.js", function(module, exports, require){ - -/*! - * EJS - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Escape the given string of `html`. - * - * @param {String} html - * @return {String} - * @api private - */ - -exports.escape = function(html){ - return String(html) - .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') - .replace(//g, '>') - .replace(/'/g, ''') - .replace(/"/g, '"'); -}; - - -}); // module: utils.js - - return require("ejs"); -})(); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/ejs.min.js b/disconf-web/html/tools/node_modules/ejs/ejs.min.js deleted file mode 100644 index cce06af3f..000000000 --- a/disconf-web/html/tools/node_modules/ejs/ejs.min.js +++ /dev/null @@ -1 +0,0 @@ -ejs=function(){function require(p){if("fs"==p)return{};if("path"==p)return{};var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');if(!mod.exports){mod.exports={};mod.call(mod.exports,mod,mod.exports,require.relative(path))}return mod.exports}require.modules={};require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig};require.register=function(path,fn){require.modules[path]=fn};require.relative=function(parent){return function(p){if("."!=p.substr(0,1))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i> ":" ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}var parse=exports.parse=function(str,options){var options=options||{},open=options.open||exports.open||"<%",close=options.close||exports.close||"%>",filename=options.filename,compileDebug=options.compileDebug!==false,buf="";buf+="var buf = [];";if(false!==options._with)buf+="\nwith (locals || {}) { (function(){ ";buf+="\n buf.push('";var lineno=1;var consumeEOL=false;for(var i=0,len=str.length;ijs.lastIndexOf("\n"))js+="\n";buf+=prefix;buf+=js;buf+=postfix}i+=end-start+close.length-1}else if(stri=="\\"){buf+="\\\\"}else if(stri=="'"){buf+="\\'"}else if(stri=="\r"){}else if(stri=="\n"){if(consumeEOL){consumeEOL=false}else{buf+="\\n";lineno++}}else{buf+=stri}}if(false!==options._with)buf+="'); })();\n} \nreturn buf.join('');";else buf+="');\nreturn buf.join('');";return buf};var compile=exports.compile=function(str,options){options=options||{};var escape=options.escape||utils.escape;var input=JSON.stringify(str),compileDebug=options.compileDebug!==false,client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined";if(compileDebug){str=["var __stack = { lineno: 1, input: "+input+", filename: "+filename+" };",rethrow.toString(),"try {",exports.parse(str,options),"} catch (err) {"," rethrow(err, __stack.input, __stack.filename, __stack.lineno);","}"].join("\n")}else{str=exports.parse(str,options)}if(options.debug)console.log(str);if(client)str="escape = escape || "+escape.toString()+";\n"+str;try{var fn=new Function("locals, filters, escape, rethrow",str)}catch(err){if("SyntaxError"==err.name){err.message+=options.filename?" in "+filename:" while compiling ejs"}throw err}if(client)return fn;return function(locals){return fn.call(this,locals,filters,escape,rethrow)}};exports.render=function(str,options){var fn,options=options||{};if(options.cache){if(options.filename){fn=cache[options.filename]||(cache[options.filename]=compile(str,options))}else{throw new Error('"cache" option requires "filename".')}}else{fn=compile(str,options)}options.__proto__=options.locals;return fn.call(options.scope,options)};exports.renderFile=function(path,options,fn){var key=path+":string";if("function"==typeof options){fn=options,options={}}options.filename=path;var str;try{str=options.cache?cache[key]||(cache[key]=read(path,"utf8")):read(path,"utf8")}catch(err){fn(err);return}fn(null,exports.render(str,options))};function resolveInclude(name,filename){var path=join(dirname(filename),name);var ext=extname(name);if(!ext)path+=".ejs";return path}exports.__express=exports.renderFile;if(require.extensions){require.extensions[".ejs"]=function(module,filename){filename=filename||module.filename;var options={filename:filename,client:true},template=fs.readFileSync(filename).toString(),fn=compile(template,options);module._compile("module.exports = "+fn.toString()+";",filename)}}else if(require.registerExtension){require.registerExtension(".ejs",function(src){return compile(src,{})})}});require.register("filters.js",function(module,exports,require){exports.first=function(obj){return obj[0]};exports.last=function(obj){return obj[obj.length-1]};exports.capitalize=function(str){str=String(str);return str[0].toUpperCase()+str.substr(1,str.length)};exports.downcase=function(str){return String(str).toLowerCase()};exports.upcase=function(str){return String(str).toUpperCase()};exports.sort=function(obj){return Object.create(obj).sort()};exports.sort_by=function(obj,prop){return Object.create(obj).sort(function(a,b){a=a[prop],b=b[prop];if(a>b)return 1;if(alen){str=str.slice(0,len);if(append)str+=append}return str};exports.truncate_words=function(str,n){var str=String(str),words=str.split(/ +/);return words.slice(0,n).join(" ")};exports.replace=function(str,pattern,substitution){return String(str).replace(pattern,substitution||"")};exports.prepend=function(obj,val){return Array.isArray(obj)?[val].concat(obj):val+obj};exports.append=function(obj,val){return Array.isArray(obj)?obj.concat(val):obj+val};exports.map=function(arr,prop){return arr.map(function(obj){return obj[prop]})};exports.reverse=function(obj){return Array.isArray(obj)?obj.reverse():String(obj).split("").reverse().join("")};exports.get=function(obj,prop){return obj[prop]};exports.json=function(obj){return JSON.stringify(obj)}});require.register("utils.js",function(module,exports,require){exports.escape=function(html){return String(html).replace(/&(?!#?[a-zA-Z0-9]+;)/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""")}});return require("ejs")}(); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/examples/client.html b/disconf-web/html/tools/node_modules/ejs/examples/client.html deleted file mode 100644 index 30dfea9f2..000000000 --- a/disconf-web/html/tools/node_modules/ejs/examples/client.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/examples/functions.ejs b/disconf-web/html/tools/node_modules/ejs/examples/functions.ejs deleted file mode 100644 index bd5610e2d..000000000 --- a/disconf-web/html/tools/node_modules/ejs/examples/functions.ejs +++ /dev/null @@ -1,9 +0,0 @@ -

    Users

    - -<% function user(user) { %> -
  • <%= user.name %> is a <%= user.age %> year old <%= user.species %>.
  • -<% } %> - -
      - <% users.map(user) %> -
    \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/examples/functions.js b/disconf-web/html/tools/node_modules/ejs/examples/functions.js deleted file mode 100644 index 607833f8d..000000000 --- a/disconf-web/html/tools/node_modules/ejs/examples/functions.js +++ /dev/null @@ -1,22 +0,0 @@ - -/** - * Module dependencies. - */ - -var ejs = require('../') - , fs = require('fs') - , path = __dirname + '/functions.ejs' - , str = fs.readFileSync(path, 'utf8'); - -var users = []; - -users.push({ name: 'Tobi', age: 2, species: 'ferret' }) -users.push({ name: 'Loki', age: 2, species: 'ferret' }) -users.push({ name: 'Jane', age: 6, species: 'ferret' }) - -var ret = ejs.render(str, { - users: users, - filename: path -}); - -console.log(ret); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/examples/list.ejs b/disconf-web/html/tools/node_modules/ejs/examples/list.ejs deleted file mode 100644 index 0b378a9c7..000000000 --- a/disconf-web/html/tools/node_modules/ejs/examples/list.ejs +++ /dev/null @@ -1,7 +0,0 @@ -<% if (names.length) { %> -
      - <% names.forEach(function(name){ %> -
    • '><%= name %>
    • - <% }) %> -
    -<% } %> \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/examples/list.js b/disconf-web/html/tools/node_modules/ejs/examples/list.js deleted file mode 100644 index ec614ed62..000000000 --- a/disconf-web/html/tools/node_modules/ejs/examples/list.js +++ /dev/null @@ -1,14 +0,0 @@ - -/** - * Module dependencies. - */ - -var ejs = require('../') - , fs = require('fs') - , str = fs.readFileSync(__dirname + '/list.ejs', 'utf8'); - -var ret = ejs.render(str, { - names: ['foo', 'bar', 'baz'] -}); - -console.log(ret); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/index.js b/disconf-web/html/tools/node_modules/ejs/index.js deleted file mode 100644 index 20bf71a3f..000000000 --- a/disconf-web/html/tools/node_modules/ejs/index.js +++ /dev/null @@ -1,2 +0,0 @@ - -module.exports = require('./lib/ejs'); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/lib/ejs.js b/disconf-web/html/tools/node_modules/ejs/lib/ejs.js deleted file mode 100644 index f36944fb2..000000000 --- a/disconf-web/html/tools/node_modules/ejs/lib/ejs.js +++ /dev/null @@ -1,357 +0,0 @@ - -/*! - * EJS - * Copyright(c) 2012 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Module dependencies. - */ - -var utils = require('./utils') - , path = require('path') - , dirname = path.dirname - , extname = path.extname - , join = path.join - , fs = require('fs') - , read = fs.readFileSync; - -/** - * Filters. - * - * @type Object - */ - -var filters = exports.filters = require('./filters'); - -/** - * Intermediate js cache. - * - * @type Object - */ - -var cache = {}; - -/** - * Clear intermediate js cache. - * - * @api public - */ - -exports.clearCache = function(){ - cache = {}; -}; - -/** - * Translate filtered code into function calls. - * - * @param {String} js - * @return {String} - * @api private - */ - -function filtered(js) { - return js.substr(1).split('|').reduce(function(js, filter){ - var parts = filter.split(':') - , name = parts.shift() - , args = parts.join(':') || ''; - if (args) args = ', ' + args; - return 'filters.' + name + '(' + js + args + ')'; - }); -}; - -/** - * Re-throw the given `err` in context to the - * `str` of ejs, `filename`, and `lineno`. - * - * @param {Error} err - * @param {String} str - * @param {String} filename - * @param {String} lineno - * @api private - */ - -function rethrow(err, str, filename, lineno){ - var lines = str.split('\n') - , start = Math.max(lineno - 3, 0) - , end = Math.min(lines.length, lineno + 3); - - // Error context - var context = lines.slice(start, end).map(function(line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' >> ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); - - // Alter exception message - err.path = filename; - err.message = (filename || 'ejs') + ':' - + lineno + '\n' - + context + '\n\n' - + err.message; - - throw err; -} - -/** - * Parse the given `str` of ejs, returning the function body. - * - * @param {String} str - * @return {String} - * @api public - */ - -var parse = exports.parse = function(str, options){ - var options = options || {} - , open = options.open || exports.open || '<%' - , close = options.close || exports.close || '%>' - , filename = options.filename - , compileDebug = options.compileDebug !== false - , buf = ""; - - buf += 'var buf = [];'; - if (false !== options._with) buf += '\nwith (locals || {}) { (function(){ '; - buf += '\n buf.push(\''; - - var lineno = 1; - - var consumeEOL = false; - for (var i = 0, len = str.length; i < len; ++i) { - var stri = str[i]; - if (str.slice(i, open.length + i) == open) { - i += open.length - - var prefix, postfix, line = (compileDebug ? '__stack.lineno=' : '') + lineno; - switch (str[i]) { - case '=': - prefix = "', escape((" + line + ', '; - postfix = ")), '"; - ++i; - break; - case '-': - prefix = "', (" + line + ', '; - postfix = "), '"; - ++i; - break; - default: - prefix = "');" + line + ';'; - postfix = "; buf.push('"; - } - - var end = str.indexOf(close, i) - , js = str.substring(i, end) - , start = i - , include = null - , n = 0; - - if ('-' == js[js.length-1]){ - js = js.substring(0, js.length - 2); - consumeEOL = true; - } - - if (0 == js.trim().indexOf('include')) { - var name = js.trim().slice(7).trim(); - if (!filename) throw new Error('filename option is required for includes'); - var path = resolveInclude(name, filename); - include = read(path, 'utf8'); - include = exports.parse(include, { filename: path, _with: false, open: open, close: close, compileDebug: compileDebug }); - buf += "' + (function(){" + include + "})() + '"; - js = ''; - } - - while (~(n = js.indexOf("\n", n))) n++, lineno++; - if (js.substr(0, 1) == ':') js = filtered(js); - if (js) { - if (js.lastIndexOf('//') > js.lastIndexOf('\n')) js += '\n'; - buf += prefix; - buf += js; - buf += postfix; - } - i += end - start + close.length - 1; - - } else if (stri == "\\") { - buf += "\\\\"; - } else if (stri == "'") { - buf += "\\'"; - } else if (stri == "\r") { - // ignore - } else if (stri == "\n") { - if (consumeEOL) { - consumeEOL = false; - } else { - buf += "\\n"; - lineno++; - } - } else { - buf += stri; - } - } - - if (false !== options._with) buf += "'); })();\n} \nreturn buf.join('');"; - else buf += "');\nreturn buf.join('');"; - return buf; -}; - -/** - * Compile the given `str` of ejs into a `Function`. - * - * @param {String} str - * @param {Object} options - * @return {Function} - * @api public - */ - -var compile = exports.compile = function(str, options){ - options = options || {}; - var escape = options.escape || utils.escape; - - var input = JSON.stringify(str) - , compileDebug = options.compileDebug !== false - , client = options.client - , filename = options.filename - ? JSON.stringify(options.filename) - : 'undefined'; - - if (compileDebug) { - // Adds the fancy stack trace meta info - str = [ - 'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };', - rethrow.toString(), - 'try {', - exports.parse(str, options), - '} catch (err) {', - ' rethrow(err, __stack.input, __stack.filename, __stack.lineno);', - '}' - ].join("\n"); - } else { - str = exports.parse(str, options); - } - - if (options.debug) console.log(str); - if (client) str = 'escape = escape || ' + escape.toString() + ';\n' + str; - - try { - var fn = new Function('locals, filters, escape, rethrow', str); - } catch (err) { - if ('SyntaxError' == err.name) { - err.message += options.filename - ? ' in ' + filename - : ' while compiling ejs'; - } - throw err; - } - - if (client) return fn; - - return function(locals){ - return fn.call(this, locals, filters, escape, rethrow); - } -}; - -/** - * Render the given `str` of ejs. - * - * Options: - * - * - `locals` Local variables object - * - `cache` Compiled functions are cached, requires `filename` - * - `filename` Used by `cache` to key caches - * - `scope` Function execution context - * - `debug` Output generated function body - * - `open` Open tag, defaulting to "<%" - * - `close` Closing tag, defaulting to "%>" - * - * @param {String} str - * @param {Object} options - * @return {String} - * @api public - */ - -exports.render = function(str, options){ - var fn - , options = options || {}; - - if (options.cache) { - if (options.filename) { - fn = cache[options.filename] || (cache[options.filename] = compile(str, options)); - } else { - throw new Error('"cache" option requires "filename".'); - } - } else { - fn = compile(str, options); - } - - options.__proto__ = options.locals; - return fn.call(options.scope, options); -}; - -/** - * Render an EJS file at the given `path` and callback `fn(err, str)`. - * - * @param {String} path - * @param {Object|Function} options or callback - * @param {Function} fn - * @api public - */ - -exports.renderFile = function(path, options, fn){ - var key = path + ':string'; - - if ('function' == typeof options) { - fn = options, options = {}; - } - - options.filename = path; - - var str; - try { - str = options.cache - ? cache[key] || (cache[key] = read(path, 'utf8')) - : read(path, 'utf8'); - } catch (err) { - fn(err); - return; - } - fn(null, exports.render(str, options)); -}; - -/** - * Resolve include `name` relative to `filename`. - * - * @param {String} name - * @param {String} filename - * @return {String} - * @api private - */ - -function resolveInclude(name, filename) { - var path = join(dirname(filename), name); - var ext = extname(name); - if (!ext) path += '.ejs'; - return path; -} - -// express support - -exports.__express = exports.renderFile; - -/** - * Expose to require(). - */ - -if (require.extensions) { - require.extensions['.ejs'] = function (module, filename) { - filename = filename || module.filename; - var options = { filename: filename, client: true } - , template = fs.readFileSync(filename).toString() - , fn = compile(template, options); - module._compile('module.exports = ' + fn.toString() + ';', filename); - }; -} else if (require.registerExtension) { - require.registerExtension('.ejs', function(src) { - return compile(src, {}); - }); -} diff --git a/disconf-web/html/tools/node_modules/ejs/lib/filters.js b/disconf-web/html/tools/node_modules/ejs/lib/filters.js deleted file mode 100644 index 45b04781a..000000000 --- a/disconf-web/html/tools/node_modules/ejs/lib/filters.js +++ /dev/null @@ -1,201 +0,0 @@ -/*! - * EJS - Filters - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * First element of the target `obj`. - */ - -exports.first = function(obj) { - return obj[0]; -}; - -/** - * Last element of the target `obj`. - */ - -exports.last = function(obj) { - return obj[obj.length - 1]; -}; - -/** - * Capitalize the first letter of the target `str`. - */ - -exports.capitalize = function(str){ - str = String(str); - return str[0].toUpperCase() + str.substr(1, str.length); -}; - -/** - * Downcase the target `str`. - */ - -exports.downcase = function(str){ - return String(str).toLowerCase(); -}; - -/** - * Uppercase the target `str`. - */ - -exports.upcase = function(str){ - return String(str).toUpperCase(); -}; - -/** - * Sort the target `obj`. - */ - -exports.sort = function(obj){ - return Object.create(obj).sort(); -}; - -/** - * Sort the target `obj` by the given `prop` ascending. - */ - -exports.sort_by = function(obj, prop){ - return Object.create(obj).sort(function(a, b){ - a = a[prop], b = b[prop]; - if (a > b) return 1; - if (a < b) return -1; - return 0; - }); -}; - -/** - * Size or length of the target `obj`. - */ - -exports.size = exports.length = function(obj) { - return obj.length; -}; - -/** - * Add `a` and `b`. - */ - -exports.plus = function(a, b){ - return Number(a) + Number(b); -}; - -/** - * Subtract `b` from `a`. - */ - -exports.minus = function(a, b){ - return Number(a) - Number(b); -}; - -/** - * Multiply `a` by `b`. - */ - -exports.times = function(a, b){ - return Number(a) * Number(b); -}; - -/** - * Divide `a` by `b`. - */ - -exports.divided_by = function(a, b){ - return Number(a) / Number(b); -}; - -/** - * Join `obj` with the given `str`. - */ - -exports.join = function(obj, str){ - return obj.join(str || ', '); -}; - -/** - * Truncate `str` to `len`. - */ - -exports.truncate = function(str, len, append){ - str = String(str); - if (str.length > len) { - str = str.slice(0, len); - if (append) str += append; - } - return str; -}; - -/** - * Truncate `str` to `n` words. - */ - -exports.truncate_words = function(str, n){ - var str = String(str) - , words = str.split(/ +/); - return words.slice(0, n).join(' '); -}; - -/** - * Replace `pattern` with `substitution` in `str`. - */ - -exports.replace = function(str, pattern, substitution){ - return String(str).replace(pattern, substitution || ''); -}; - -/** - * Prepend `val` to `obj`. - */ - -exports.prepend = function(obj, val){ - return Array.isArray(obj) - ? [val].concat(obj) - : val + obj; -}; - -/** - * Append `val` to `obj`. - */ - -exports.append = function(obj, val){ - return Array.isArray(obj) - ? obj.concat(val) - : obj + val; -}; - -/** - * Map the given `prop`. - */ - -exports.map = function(arr, prop){ - return arr.map(function(obj){ - return obj[prop]; - }); -}; - -/** - * Reverse the given `obj`. - */ - -exports.reverse = function(obj){ - return Array.isArray(obj) - ? obj.reverse() - : String(obj).split('').reverse().join(''); -}; - -/** - * Get `prop` of the given `obj`. - */ - -exports.get = function(obj, prop){ - return obj[prop]; -}; - -/** - * Packs the given `obj` into json string - */ -exports.json = function(obj){ - return JSON.stringify(obj); -}; diff --git a/disconf-web/html/tools/node_modules/ejs/lib/utils.js b/disconf-web/html/tools/node_modules/ejs/lib/utils.js deleted file mode 100644 index 8df6c6a57..000000000 --- a/disconf-web/html/tools/node_modules/ejs/lib/utils.js +++ /dev/null @@ -1,24 +0,0 @@ - -/*! - * EJS - * Copyright(c) 2010 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Escape the given string of `html`. - * - * @param {String} html - * @return {String} - * @api private - */ - -exports.escape = function(html){ - return String(html) - .replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&') - .replace(//g, '>') - .replace(/'/g, ''') - .replace(/"/g, '"'); -}; - diff --git a/disconf-web/html/tools/node_modules/ejs/package.json b/disconf-web/html/tools/node_modules/ejs/package.json deleted file mode 100644 index dc0d91a66..000000000 --- a/disconf-web/html/tools/node_modules/ejs/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "ejs", - "description": "Embedded JavaScript templates", - "version": "0.8.5", - "author": { - "name": "TJ Holowaychuk", - "email": "tj@vision-media.ca" - }, - "keywords": [ - "template", - "engine", - "ejs" - ], - "devDependencies": { - "mocha": "*", - "should": "*" - }, - "main": "./lib/ejs.js", - "repository": { - "type": "git", - "url": "git://github.com/visionmedia/ejs.git" - }, - "scripts": { - "test": "mocha --require should --reporter spec" - }, - "readme": "# EJS\n\nEmbedded JavaScript templates.\n\n[![Build Status](https://travis-ci.org/visionmedia/ejs.png)](https://travis-ci.org/visionmedia/ejs)\n\n## Installation\n\n $ npm install ejs\n\n## Features\n\n * Complies with the [Express](http://expressjs.com) view system\n * Static caching of intermediate JavaScript\n * Unbuffered code for conditionals etc `<% code %>`\n * Escapes html by default with `<%= code %>`\n * Unescaped buffering with `<%- code %>`\n * Supports tag customization\n * Filter support for designer-friendly templates\n * Includes\n * Client-side support\n * Newline slurping with `<% code -%>` or `<% -%>` or `<%= code -%>` or `<%- code -%>`\n\n## Example\n\n <% if (user) { %>\n\t

    <%= user.name %>

    \n <% } %>\n \n## Try out a live example now\n\n\n\n## Usage\n\n ejs.compile(str, options);\n // => Function\n\n ejs.render(str, options);\n // => str\n\n## Options\n\n - `cache` Compiled functions are cached, requires `filename`\n - `filename` Used by `cache` to key caches\n - `scope` Function execution context\n - `debug` Output generated function body\n - `compileDebug` When `false` no debug instrumentation is compiled\n - `client` Returns standalone compiled function\n - `open` Open tag, defaulting to \"<%\"\n - `close` Closing tag, defaulting to \"%>\"\n - * All others are template-local variables\n\n## Includes\n\n Includes are relative to the template with the `include` statement,\n for example if you have \"./views/users.ejs\" and \"./views/user/show.ejs\"\n you would use `<% include user/show %>`. The included file(s) are literally\n included into the template, _no_ IO is performed after compilation, thus\n local variables are available to these included templates.\n\n```\n
      \n <% users.forEach(function(user){ %>\n <% include user/show %>\n <% }) %>\n
    \n```\n\n## Custom delimiters\n\nCustom delimiters can also be applied globally:\n\n var ejs = require('ejs');\n ejs.open = '{{';\n ejs.close = '}}';\n\nWhich would make the following a valid template:\n\n

    {{= title }}

    \n\n## Filters\n\nEJS conditionally supports the concept of \"filters\". A \"filter chain\"\nis a designer friendly api for manipulating data, without writing JavaScript.\n\nFilters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters:\n\nTemplate:\n\n

    <%=: users | map:'name' | join %>

    \n\nOutput:\n\n

    Tj, Mape, Guillermo

    \n\nRender call:\n\n ejs.render(str, {\n users: [\n { name: 'tj' },\n { name: 'mape' },\n { name: 'guillermo' }\n ]\n });\n\nOr perhaps capitalize the first user's name for display:\n\n

    <%=: users | first | capitalize %>

    \n\n## Filter list\n\nCurrently these filters are available:\n\n - first\n - last\n - capitalize\n - downcase\n - upcase\n - sort\n - sort_by:'prop'\n - size\n - length\n - plus:n\n - minus:n\n - times:n\n - divided_by:n\n - join:'val'\n - truncate:n\n - truncate_words:n\n - replace:pattern,substitution\n - prepend:val\n - append:val\n - map:'prop'\n - reverse\n - get:'prop'\n\n## Adding filters\n\n To add a filter simply add a method to the `.filters` object:\n \n```js\nejs.filters.last = function(obj) {\n return obj[obj.length - 1];\n};\n```\n\n## Layouts\n\n Currently EJS has no notion of blocks, only compile-time `include`s,\n however you may still utilize this feature to implement \"layouts\" by\n simply including a header and footer like so:\n\n```html\n<% include head %>\n

    Title

    \n

    My page

    \n<% include foot %>\n```\n\n## client-side support\n\n include `./ejs.js` or `./ejs.min.js` and `require(\"ejs\").compile(str)`.\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", - "readmeFilename": "Readme.md", - "bugs": { - "url": "https://github.com/visionmedia/ejs/issues" - }, - "homepage": "https://github.com/visionmedia/ejs", - "_id": "ejs@0.8.5", - "_from": "ejs@" -} diff --git a/disconf-web/html/tools/node_modules/ejs/support/compile.js b/disconf-web/html/tools/node_modules/ejs/support/compile.js deleted file mode 100644 index 6d3a5eb2f..000000000 --- a/disconf-web/html/tools/node_modules/ejs/support/compile.js +++ /dev/null @@ -1,177 +0,0 @@ - -/** - * Module dependencies. - */ - -var fs = require('fs'); - -/** - * Arguments. - */ - -var args = process.argv.slice(2) - , pending = args.length - , files = {}; - -console.log(''); - -// parse arguments - -args.forEach(function(file){ - var mod = file.replace('lib/', ''); - fs.readFile(file, 'utf8', function(err, js){ - if (err) throw err; - console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file); - files[file] = parse(js); - --pending || compile(); - }); -}); - -/** - * Parse the given `js`. - */ - -function parse(js) { - return parseInheritance(parseConditionals(js)); -} - -/** - * Parse __proto__. - */ - -function parseInheritance(js) { - return js - .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){ - return child + '.prototype = new ' + parent + ';\n' - + child + '.prototype.constructor = '+ child + ';\n'; - }); -} - -/** - * Parse the given `js`, currently supporting: - * - * 'if' ['node' | 'browser'] - * 'end' - * - */ - -function parseConditionals(js) { - var lines = js.split('\n') - , len = lines.length - , buffer = true - , browser = false - , buf = [] - , line - , cond; - - for (var i = 0; i < len; ++i) { - line = lines[i]; - if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) { - cond = RegExp.$1; - buffer = browser = 'browser' == cond; - } else if (/^ *\/\/ *end/.test(line)) { - buffer = true; - browser = false; - } else if (browser) { - buf.push(line.replace(/^( *)\/\//, '$1')); - } else if (buffer) { - buf.push(line); - } - } - - return buf.join('\n'); -} - -/** - * Compile the files. - */ - -function compile() { - var buf = ''; - buf += 'ejs = (function(){\n'; - buf += '\n// CommonJS require()\n\n'; - buf += browser.require + '\n\n'; - buf += 'require.modules = {};\n\n'; - buf += 'require.resolve = ' + browser.resolve + ';\n\n'; - buf += 'require.register = ' + browser.register + ';\n\n'; - buf += 'require.relative = ' + browser.relative + ';\n\n'; - args.forEach(function(file){ - var js = files[file]; - file = file.replace('lib/', ''); - buf += '\nrequire.register("' + file + '", function(module, exports, require){\n'; - buf += js; - buf += '\n}); // module: ' + file + '\n'; - }); - buf += '\n return require("ejs");\n})();'; - fs.writeFile('ejs.js', buf, function(err){ - if (err) throw err; - console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js'); - console.log(); - }); -} - -// refactored version of weepy's -// https://github.com/weepy/brequire/blob/master/browser/brequire.js - -var browser = { - - /** - * Require a module. - */ - - require: function require(p){ - if ('fs' == p) return {}; - if ('path' == p) return {}; - var path = require.resolve(p) - , mod = require.modules[path]; - if (!mod) throw new Error('failed to require "' + p + '"'); - if (!mod.exports) { - mod.exports = {}; - mod.call(mod.exports, mod, mod.exports, require.relative(path)); - } - return mod.exports; - }, - - /** - * Resolve module path. - */ - - resolve: function(path){ - var orig = path - , reg = path + '.js' - , index = path + '/index.js'; - return require.modules[reg] && reg - || require.modules[index] && index - || orig; - }, - - /** - * Return relative require(). - */ - - relative: function(parent) { - return function(p){ - if ('.' != p.substr(0, 1)) return require(p); - - var path = parent.split('/') - , segs = p.split('/'); - path.pop(); - - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - if ('..' == seg) path.pop(); - else if ('.' != seg) path.push(seg); - } - - return require(path.join('/')); - }; - }, - - /** - * Register a module. - */ - - register: function(path, fn){ - require.modules[path] = fn; - } -}; \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/ejs/test/ejs.js b/disconf-web/html/tools/node_modules/ejs/test/ejs.js deleted file mode 100644 index 7df7ace92..000000000 --- a/disconf-web/html/tools/node_modules/ejs/test/ejs.js +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Module dependencies. - */ - -var ejs = require('..') - , fs = require('fs') - , read = fs.readFileSync - , assert = require('should'); - -/** - * Load fixture `name`. - */ - -function fixture(name) { - return read('test/fixtures/' + name, 'utf8').replace(/\r/g, ''); -} - -/** - * User fixtures. - */ - -var users = []; -users.push({ name: 'tobi' }); -users.push({ name: 'loki' }); -users.push({ name: 'jane' }); - -describe('ejs.compile(str, options)', function(){ - it('should compile to a function', function(){ - var fn = ejs.compile('

    yay

    '); - fn().should.equal('

    yay

    '); - }) - - it('should throw if there are syntax errors', function(){ - try { - ejs.compile(fixture('fail.ejs')); - } catch (err) { - err.message.should.include('compiling ejs'); - - try { - ejs.compile(fixture('fail.ejs'), { filename: 'fail.ejs' }); - } catch (err) { - err.message.should.include('fail.ejs'); - return; - } - } - - assert(false, 'compiling a file with invalid syntax should throw an exception'); - }) - - it('should allow customizing delimiters', function(){ - var fn = ejs.compile('

    {= name }

    ', { open: '{', close: '}' }); - fn({ name: 'tobi' }).should.equal('

    tobi

    '); - - var fn = ejs.compile('

    ::= name ::

    ', { open: '::', close: '::' }); - fn({ name: 'tobi' }).should.equal('

    tobi

    '); - - var fn = ejs.compile('

    (= name )

    ', { open: '(', close: ')' }); - fn({ name: 'tobi' }).should.equal('

    tobi

    '); - }) - - it('should default to using ejs.open and ejs.close', function(){ - ejs.open = '{'; - ejs.close = '}'; - var fn = ejs.compile('

    {= name }

    '); - fn({ name: 'tobi' }).should.equal('

    tobi

    '); - - var fn = ejs.compile('

    |= name |

    ', { open: '|', close: '|' }); - fn({ name: 'tobi' }).should.equal('

    tobi

    '); - delete ejs.open; - delete ejs.close; - }) - - it('should have a working client option', function(){ - var fn = ejs.compile('

    <%= foo %>

    ', { client: true }); - var str = fn.toString(); - eval('var preFn = ' + str); - preFn({ foo: 'bar' }).should.equal('

    bar

    '); - }) -}) - -describe('ejs.render(str, options)', function(){ - it('should render the template', function(){ - ejs.render('

    yay

    ') - .should.equal('

    yay

    '); - }) - - it('should accept locals', function(){ - ejs.render('

    <%= name %>

    ', { name: 'tobi' }) - .should.equal('

    tobi

    '); - }) -}) - -describe('ejs.renderFile(path, options, fn)', function(){ - it('should render a file', function(done){ - ejs.renderFile('test/fixtures/para.ejs', function(err, html){ - if (err) return done(err); - html.should.equal('

    hey

    '); - done(); - }); - }) - - it('should accept locals', function(done){ - var options = { name: 'tj', open: '{', close: '}' }; - ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ - if (err) return done(err); - html.should.equal('

    tj

    '); - done(); - }); - }) - - it('should not catch err threw by callback', function(done){ - var options = { name: 'tj', open: '{', close: '}' }; - var counter = 0; - try { - ejs.renderFile('test/fixtures/user.ejs', options, function(err, html){ - counter++; - if (err) { - err.message.should.not.equal('Exception in callback'); - return done(err); - } - throw new Error('Exception in callback'); - }); - } catch (err) { - counter.should.equal(1); - err.message.should.equal('Exception in callback'); - done(); - } - }) -}) - -describe('<%=', function(){ - it('should escape -``` -使用: - -```js -// EventProxy此时是一个全局变量 -var ep = new EventProxy(); -``` - -#### SeaJS用户 -SeaJS下只需配置别名,然后`require`引用即可使用。 - -```js -// 配置 -seajs.config({ - alias: { - eventproxy: 'https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy.js' - } -}); -// 使用 -seajs.use(['eventproxy'], function (EventProxy) { - // TODO -}); -// 或者 -define('test', function (require, exports, modules) { - var EventProxy = require('eventproxy'); -}); -``` - -#### RequireJS用户 -RequireJS实现的是AMD规范。 - -```js -// 配置路径 -require.config({ - paths: { - eventproxy: "https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy" - } -}); -// 使用 -require(["eventproxy"], function (EventProxy) { - // TODO -}); -``` -## 异步协作 -### 多类型异步协作 -此处以页面渲染为场景,渲染页面需要模板、数据。假设都需要异步读取。 - -```js -var ep = new EventProxy(); -ep.all('tpl', 'data', function (tpl, data) { - // 在所有指定的事件触发后,将会被调用执行 - // 参数对应各自的事件名 -}); -fs.readFile('template.tpl', 'utf-8', function (err, content) { - ep.emit('tpl', content); -}); -db.get('some sql', function (err, result) { - ep.emit('data', result); -}); -``` - -`all`方法将handler注册到事件组合上。当注册的多个事件都触发后,将会调用handler执行,每个事件传递的数据,将会依照事件名顺序,传入handler作为参数。 -#### 快速创建 -EventProxy提供了`create`静态方法,可以快速完成注册`all`事件。 - -```js -var ep = EventProxy.create('tpl', 'data', function (tpl, data) { - // TODO -}); -``` - -以上方法等效于 - -```js -var ep = new EventProxy(); -ep.all('tpl', 'data', function (tpl, data) { - // TODO -}); -``` - -### 重复异步协作 -此处以读取目录下的所有文件为例,在异步操作中,我们需要在所有异步调用结束后,执行某些操作。 - -```js -var ep = new EventProxy(); -ep.after('got_file', files.length, function (list) { - // 在所有文件的异步执行结束后将被执行 - // 所有文件的内容都存在list数组中 -}); -for (var i = 0; i < files.length; i++) { - fs.readFile(files[i], 'utf-8', function (err, content) { - // 触发结果事件 - ep.emit('got_file', content); - }); -} -``` - -`after`方法适合重复的操作,比如读取10个文件,调用5次数据库等。将handler注册到N次相同事件的触发上。达到指定的触发数,handler将会被调用执行,每次触发的数据,将会按触发顺序,存为数组作为参数传入。 - -### 持续型异步协作 -此处以股票为例,数据和模板都是异步获取,但是数据会持续刷新,视图会需要重新刷新。 - -```js -var ep = new EventProxy(); -ep.tail('tpl', 'data', function (tpl, data) { - // 在所有指定的事件触发后,将会被调用执行 - // 参数对应各自的事件名的最新数据 -}); -fs.readFile('template.tpl', 'utf-8', function (err, content) { - ep.emit('tpl', content); -}); -setInterval(function () { - db.get('some sql', function (err, result) { - ep.emit('data', result); - }); -}, 2000); -``` - -`tail`与`all`方法比较类似,都是注册到事件组合上。不同在于,指定事件都触发之后,如果事件依旧持续触发,将会在每次触发时调用handler,极像一条尾巴。 - - -## 基本事件 -通过事件实现异步协作是EventProxy的主要亮点。除此之外,它还是一个基本的事件库。携带如下基本API - -- `on`/`addListener`,绑定事件监听器 -- `emit`,触发事件 -- `once`,绑定只执行一次的事件监听器 -- `removeListener`,移除事件的监听器 -- `removeAllListeners`,移除单个事件或者所有事件的监听器 - -为了照顾各个环境的开发者,上面的方法多具有别名。 - -- YUI3使用者,`subscribe`和`fire`你应该知道分别对应的是`on`/`addListener`和`emit`。 -- jQuery使用者,`trigger`对应的方法是`emit`,`bind`对应的就是`on`/`addListener`。 -- `removeListener`和`removeAllListeners`其实都可以通过别名`unbind`完成。 - -所以在你的环境下,选用你喜欢的API即可。 - -更多API的描述请访问[API Docs](http://html5ify.com/eventproxy/api.html)。 - -## 异常处理 -在异步方法中,实际上,异常处理需要占用一定比例的精力。在过去一段时间内,我们都是通过额外添加`error`事件来进行处理的,代码大致如下: - -```js -exports.getContent = function (callback) { - var ep = new EventProxy(); - ep.all('tpl', 'data', function (tpl, data) { - // 成功回调 - callback(null, { - template: tpl, - data: data - }); - }); - // 侦听error事件 - ep.bind('error', function (err) { - // 卸载掉所有handler - ep.unbind(); - // 异常回调 - callback(err); - }); - fs.readFile('template.tpl', 'utf-8', function (err, content) { - if (err) { - // 一旦发生异常,一律交给error事件的handler处理 - return ep.emit('error', err); - } - ep.emit('tpl', content); - }); - db.get('some sql', function (err, result) { - if (err) { - // 一旦发生异常,一律交给error事件的handler处理 - return ep.emit('error', err); - } - ep.emit('data', result); - }); -}; -``` - -代码量因为异常的处理,一下子上去了很多。在这里EventProxy经过很多实践后,我们根据我们的最佳实践提供了优化的错误处理方案。 - -```js -exports.getContent = function (callback) { - var ep = new EventProxy(); - ep.all('tpl', 'data', function (tpl, data) { - // 成功回调 - callback(null, { - template: tpl, - data: data - }); - }); - // 添加error handler - ep.fail(callback); - - fs.readFile('template.tpl', 'utf-8', ep.done('tpl')); - db.get('some sql', ep.done('data')); -}; -``` - -上述代码优化之后,业务开发者几乎不用关心异常处理了。代码量降低效果明显。 -这里代码的转换,也许有开发者并不放心。其实秘诀在`fail`方法和`done`方法中。 - -### 神奇的fail - -```js -ep.fail(callback); -// 由于参数位相同,它实际是 -ep.fail(function (err) { - callback(err); -}); - -// 等价于 -ep.bind('error', function (err) { - // 卸载掉所有handler - ep.unbind(); - // 异常回调 - callback(err); -}); -``` - -`fail`方法侦听了`error`事件,默认处理卸载掉所有handler,并调用回调函数。 - -### 神奇的done - -```js -ep.done('tpl'); -// 等价于 -function (err, content) { - if (err) { - // 一旦发生异常,一律交给error事件的handler处理 - return ep.emit('error', err); - } - ep.emit('tpl', content); -} -``` - -在Node的最佳实践中,回调函数第一个参数一定会是一个`error`对象。检测到异常后,将会触发`error`事件。剩下的参数,将触发事件,传递给对应handler处理。 - -#### done也接受回调函数 -`done`方法除了接受事件名外,还接受回调函数。如果是函数时,它将剔除第一个`error`对象(此时为`null`)后剩余的参数,传递给该回调函数作为参数。该回调函数无需考虑异常处理。 - -```js -ep.done(function (content) { - // 这里无需考虑异常 - // 手工emit - ep.emit('someevent', newcontent); -}); -``` - -当然手工emit的方式并不太好,我们更进一步的版本: - -```js -ep.done('tpl', function (tpl) { - // 将内容更改后,返回即可 - return tpl.trim(); -}); -``` - -#### 注意事项 -如果`emit`需要传递多个参数时,`ep.done(event, fn)`的方式不能满足需求,还是需要`ep.done(fn)`,进行手工`emit`多个参数。 - -### 神奇的group -`fail`除了用于协助`all`方法完成外,也能协助`after`中的异常处理。另外,在`after`的回调函数中,结果顺序是与用户`emit`的顺序有关。为了满足返回数据按发起异步调用的顺序排列,`EventProxy`提供了`group`方法。 - -```js -var ep = new EventProxy(); -ep.after('got_file', files.length, function (list) { - // 在所有文件的异步执行结束后将被执行 - // 所有文件的内容都存在list数组中,按顺序排列 -}); -for (var i = 0; i < files.length; i++) { - fs.readFile(files[i], 'utf-8', ep.group('got_file')); -} -``` -`group`秉承`done`函数的设计,它包含异常的传递。同时它还隐含了对返回数据进行编号,在结束时,按顺序返回。 - -```js -ep.group('got_file'); -// 约等价于 -function (err, data) { - if (err) { - return ep.emit('error', err); - } - ep.emit('got_file', data); -}; -``` - -当回调函数的数据还需要进行加工时,可以给`group`带上回调函数,只要在操作后将数据返回即可: - -```js -ep.group('got_file', function (data) { - // some code - return data; -}); -``` - -### 异步事件触发: emitLater && doneLater - -在node中,`emit`方法是同步的,EventProxy中的`emit`,`trigger`等跟node的风格一致,也是同步的。看下面这段代码,可能眼尖的同学一下就发现了隐藏的bug: -```js -var ep = EventProxy.create(); - -db.check('key', function (err, permission) { - if (err) { - return ep.emit('error', err); - } - ep.emit('check', permission); -}); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); -``` - -没错,万一`db.check`的`callback`被同步执行了,在`ep`监听`check`事件之前,它就已经被抛出来了,后续逻辑没办法继续执行。尽管node的约定是所有的`callback`都是需要异步返回的,但是如果这个方法是由第三方提供的,我们没有办法保证`db.check`的`callback`一定会异步执行,所以我们的代码通常就变成了这样: - -```js -var ep = EventProxy.create(); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); - -db.check('key', function (err, permission) { - if (err) { - return ep.emit('error', err); - } - ep.emit('check', permission); -}); -``` -我们被迫把`db.check`挪到最后,保证事件先被监听,再执行`db.check`。`check`->`get`->`render`的逻辑,在代码中看起来变成了`get`->`render`->`check`。如果整个逻辑更加复杂,这种风格将会让代码很难读懂。 - -这时候,我们需要的就是 __异步事件触发__: - -```js -var ep = EventProxy.create(); - -db.check('key', function (err, permission) { - if (err) { - return ep.emitLater('error', err); - } - ep.emitLater('check', permission); -}); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); -``` -上面代码中,我们把`db.check`的回调函数中的事件通过`emitLater`触发,这样,就算`db.check`的回调函数被同步执行了,事件的触发也还是异步的,`ep`在当前事件循环中监听了所有的事件,之后的事件循环中才会去触发`check`事件。代码顺序将和逻辑顺序保持一致。 -当然,这么复杂的代码,必须可以像`ep.done()`一样通过`doneLater`来解决: - -```js -var ep = EventProxy.create(); - -db.check('key', ep.doneLater('check')); - -ep.once('check', function (permission) { - permission && db.get('key', ep.done('get')); -}); - -ep.once('get', function (data) { - render(data); -}); - -ep.fail(errorHandler); -``` -最终呈现出来的,是一段简洁且清晰的代码。 - - -## 注意事项 -- 请勿使用`all`作为业务中的事件名。该事件名为保留事件。 -- 异常处理部分,请遵循Node的最佳实践(回调函数首个参数为异常传递位)。 - -## [贡献者们](https://github.com/JacksonTian/eventproxy/graphs/contributors) -谢谢EventProxy的使用者们,享受EventProxy的过程,也给EventProxy回馈良多。 - -```bash - project : eventproxy - repo age : 1 year, 10 months - active : 58 days - commits : 136 - files : 18 - authors : - 123 Jackson Tian 90.4% - 6 fengmk2 4.4% - 4 dead-horse 2.9% - 1 haoxin 0.7% - 1 redky 0.7% - 1 yaoazhen 0.7% - -``` - -## License - -[The MIT License](https://github.com/JacksonTian/eventproxy/blob/master/MIT-License)。请自由享受开源。 - -## 捐赠 -如果您觉得本模块对您有帮助,欢迎请作者一杯咖啡 - -[![捐赠EventProxy](https://img.alipay.com/sys/personalprod/style/mc/btn-index.png)](https://me.alipay.com/jacksontian) - - -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/JacksonTian/eventproxy/trend.png)](https://bitdeli.com/free "Bitdeli Badge") - diff --git a/disconf-web/html/tools/node_modules/eventproxy/README_en.md b/disconf-web/html/tools/node_modules/eventproxy/README_en.md deleted file mode 100644 index 3af106bb3..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/README_en.md +++ /dev/null @@ -1,503 +0,0 @@ -EventProxy [![Build Status](https://secure.travis-ci.org/JacksonTian/eventproxy.png)](http://travis-ci.org/JacksonTian/eventproxy) -====== - -> There is no deep nested callback issue in this world. —— [Jackson Tian](http://weibo.com/shyvo) - -> There is no nesting callback originally, more people have written, resulting in appearance `}}}}}}}}}}}}`. —— [fengmk2](http://fengmk2.github.com) - -* [API Documentation](http://html5ify.com/eventproxy/api.html) -* [jscoverage 97%](http://html5ify.com/eventproxy/coverage.html) -* [Annotated Source](http://html5ify.com/eventproxy/eventproxy.html) - -EventProxy is only a lightweight tool, which brings about a thinking change on event programming. There are some features: - -1. Decouples complicated business nesting problems with event mechanism. -2. Resolve the deep callback nesting issue. -3. Changes serial waiting to parallel waiting, promoting executing efficiency under asynchronous collaboration sceneries. -4. Exception handling friendly. -5. Can be used in browser and Node.js both. Compatible with CMD, AMD and CommonJS module. - -Nowadays, no deep nesting, parallel: - -```js -var ep = EventProxy.create("template", "data", "l10n", function (template, data, l10n) { - _.template(template, data, l10n); -}); - -$.get("template", function (template) { - // something - ep.emit("template", template); -}); -$.get("data", function (data) { - // something - ep.emit("data", data); -}); -$.get("l10n", function (l10n) { - // something - ep.emit("l10n", l10n); -}); -``` - -Past, deep nesting, serial: - -```js -var render = function (template, data) { - _.template(template, data); -}; -$.get("template", function (template) { - // something - $.get("data", function (data) { - // something - $.get("l10n", function (l10n) { - // something - render(template, data, l10n); - }); - }); -}); -``` - -## Installation - -### For Node -Install with NPM: - -```bash -$ npm install eventproxy -``` - -Usage: - -```js -var EventProxy = require('eventproxy'); -``` - -### For browser -Following examples direct resource address of Github, and you can also download [resource file](https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy.js) to your own project. 500 lines in total including comments and blank lines. To ensure the easy integrate with your project, EventProxy doesn't provide the minified version. You can use Uglify, YUI Compressor or Google Closure Complier to compress it. - -#### Common Environment -Just insert the script tag into HTML page: - -```html - -``` - -Usage: - -```js -// EventProxy is a global variable now -var ep = new EventProxy(); -``` - -#### For SeaJS -Only need to configure alias, and then requires it. - -```js -// Configuration -seajs.config({ - alias: { - eventproxy: 'https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy.js' - } -}); -// Usage -seajs.use(['eventproxy'], function (EventProxy) { - // TODO -}); -// or -define('test', function (require, exports, modules) { - var EventProxy = require('eventproxy'); -}); -``` - -#### For RequireJS -The RequireJS implemented AMD specifications - -```js -// Configure path -require.config({ - paths: { - eventproxy: "https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy" - } -}); -// Usage -require(["eventproxy"], function (EventProxy) { - // TODO -}); -``` - -## Asynchronous call -#### Multiple type asynchronous call -For example, render a page, template and data are needed. Suppose must get them asynchronously. - -```js -var ep = new EventProxy(); -ep.all('tpl', 'data', function (tpl, data) { - // Executed when all specified events are fired. - // Parameters corresponds with each event name -}); -fs.readFile('template.tpl', 'utf-8', function (err, content) { - ep.emit('tpl', content); -}); -db.get('some sql', function (err, result) { - ep.emit('data', result); -}); -``` - -`all` method will register handler to events combination. When more than one registered events are fired, handler will be invoked, transferred data of each event will be transferred to handler as parameters in the order of event names. - -#### Shortcut -EventProxy has provided static method, fast finishing registering all event. - -```js -var ep = EventProxy.create('tpl', 'data', function (tpl, data) { - // TODO -}); -``` - -Method above equals to:
 - -```js -var ep = new EventProxy(); -ep.all('tpl', 'data', function (tpl, data) { - // TODO -}); -``` - -### Repeatly asynchronous collaboration -Take reading all files under a folder for example, in asynchronous operation, we need execute some operations after all asynchronous invokes. - -```js -var ep = new EventProxy(); -ep.after('got_file', files.length, function (list) { - // Executed after all asynchronous executions on files finish. - //All file contents are saved in list arrays. }); -for (var i = 0; i < files.length; i++) { - fs.readFile(files[i], 'utf-8', function (err, content) { - // Fire result event - ep.emit('got_file', content); - }); -} -``` - -`after` method suitable for repeat operations, such as reading 10 files, accessing database for 5 times. Registers handler on the fire of N times same event. When reaches the specified fire times, handler will be invoked, data from each fire will be saved as array and transferred as parameters in the fire orders. - -### Continuous asynchronous collaboration -Taking stocks for example, data and templates are got asynchronously, while data will continuously be refreshed, view will need to be refreshed over again. - -```js -var ep = new EventProxy(); -ep.tail('tpl', 'data', function (tpl, data) { - // Executed when all specified events are fired. - // Parameters correspond with latest data of each event name - }); -fs.readFile('template.tpl', 'utf-8', function (err, content) { - ep.emit('tpl', content); -}); -setInterval(function () { - db.get('some sql', function (err, result) { - ep.emit('data', result); - }); -}, 2000); -``` - -`tail` is similar to `all` method, which is also registered on event combination. The difference is, when specified events are all fired, if events are continuously fired, handler will be invoked after each event fire, which is like a tail. - -## Basic Events -The realization of asynchronous collaboration through event is the main highlight of EventProxy. Besides, it is a basic event lib, with basic APIs as follows: - -- `on`/`addListener`, binding on event listener -- `emit`, fire event -- `once`, binding on event listener that only execute once -- `removeListener`, remove event listener -- `removeAllListeners`, remove single event or all event listeners - -To consider developers of each environment, most of the methods above have alias names. - -- YUI3 users, you should know `subscribe` and `fire` correspond with `on`/`addListener` and `emit`. -- jQuery users, trigger corresponds with `emit`, `bind` corresponds with `on`/`addListener`. -- `removeListener` and `removeAllListeners` are aliased by `unbind`. - -So choose your favorite API under your environment. - -More API descriptions please access [API Docs](http://html5ify.com/eventproxy/api.html). - -## Exception Handling -In asynchronous method, actually, exception handling needs rather certain energy. During past times, we’ve dealt through adding error event, code as follows: - -```js -exports.getContent = function (callback) { - var ep = new EventProxy(); - ep.all('tpl', 'data', function (tpl, data) { - // Successfully callback - callback(null, { - template: tpl, - data: data - }); - }); - // Listen to error event - ep.bind('error', function (err) { - // Redmove all handlers - ep.unbind(); - // Exception callback - callback(err); - }); - fs.readFile('template.tpl', 'utf-8', function (err, content) { - if (err) { - // Once exception occurs, hand to error handler to deal - return ep.emit('error', err); - } - ep.emit('tpl', content); - }); - db.get('some sql', function (err, result) { - if (err) { - // Once exception occurs, hand to error handler to deal - return ep.emit('error', err); - } - ep.emit('data', result); - }); -}; -``` - -Code lines ascends much for exception handling. After times of practice by EventProxy, we have provided optimized exception handling methods. - -```js -exports.getContent = function (callback) { - var ep = new EventProxy(); - ep.all('tpl', 'data', function (tpl, data) { - // Successfully callback - callback(null, { - template: tpl, - data: data - }); - }); - // Adding error handler - ep.fail(callback); - - fs.readFile('template.tpl', 'utf-8', ep.done('tpl')); - db.get('some sql', ep.done('data')); -}; -``` - -After code optimization above, business developers almost don’t have to care about exception handling. Code lines descend apparently. Some developers may not be assured about code converts here. The secret lies in method of fail and done. - -### Amazing `fail` - -```js -ep.fail(callback); -// For the same parameters account, it is actually: -ep.fail(function (err) { - callback(err); -}); - -// Equals to -ep.bind('error', function (err) { - // Remove all handler - ep.unbind(); - // Exception callback - callback(err); -}); -``` - -`fail` method listens to `error` event, removes all handlers by default, then invoke callback method. - -### Amazing `done` - -```js -ep.done('tpl'); -// Equals to -function (err, content) { - if (err) { - // Once exception occurs, hand to error event handler to deal - return ep.emit('error', err); - } - ep.emit('tpl', content); -} -``` - -In Node best practice, the first parameter of callback should be an error object(or null). `error` event will be fired after detecting exception. The remaining parameters will fire events and be transferred to correspond handler to deal. - -#### `done` accept callback also -The method of `done` accepts callback function excepts event names. If it is function, it will remove the remaining parameters after the first `error` object(it is `null`), transfers to the callback function as parameters. The callback function will not need to consider exception handling. - -```js -ep.done(function (content) { - // No need to consider exception handling again -}); -``` - -### Amazing `group` -`fail` can help to handle exception in `after` except the `all` method. Besides, in the callback of after, the order of result is related to the order of emit used by user. In order to get return results in the order of calling asynchronous invoke, EventProxy provides the group method. - -```js -var ep = new EventProxy(); -ep.after('got_file', files.length, function (list) { - // Executes after all file asynchronous executions - // All file contents are saved in list arrays, in order -}); -for (var i = 0; i < files.length; i++) { - fs.readFile(files[i], 'utf-8', ep.group('got_file')); -} -``` - -The `group` method follows the done method design, including exception transferring. At the same time, it implies number for the return results, return results in order when finishes. - -```js -ep.group('got_file'); -// Similar equals to -function (err, data) { - if (err) { - return ep.emit('error', err); - } - ep.emit('got_file', data); -}; -``` - -When callback data needs to process, adding callback function on the `group` method, only return result data after processing. - -```js -ep.group('got_file', function (data) { - // some code - return data; -}); -``` - -### Asynchronous event emit: emitLater && doneLater -In node, `emit` is a synchronous method, `emit`and `trigger` in EventProxy also are synchronous method like node. Look at code below, maybe you can find out what's wrong with it. - -```js -var ep = EventProxy.create(); - -db.check('key', function (err, permission) { - if (err) { - return ep.emit('error', err); - } - ep.emit('check', permission); -}); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); -``` -Just in case `callback` in `db.check` was synchronous execution, the `check` event will emit before `ep` listen `check`. Then the code won't work as we expect. Even though in node, we should keep all callback asynchronous execution, but we can't ensure everyone can accomplish. So we must write code like this: - -```js -var ep = EventProxy.create(); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); - -db.check('key', function (err, permission) { - if (err) { - return ep.emit('error', err); - } - ep.emit('check', permission); -}); -``` - -We have to move `db.check` to the end of the code, to make sure `ep` listen all the events first. Then the code look like `get`->`render`->`check`, but the execution order is `check`->`get`->`render`, this kind of code is hard to understand. - -So we need __Asynchronous event emit__: - -```js -var ep = EventProxy.create(); - -db.check('key', function (err, permission) { - if (err) { - return ep.emitLater('error', err); - } - ep.emitLater('check', permission); -}); - -ep.once('check', function (permission) { - permission && db.get('key', function (err, data) { - if (err) { - return ep.emit('error'); - } - ep.emit('get', data); - }); -}); - -ep.once('get', function (err, data) { - if (err) { - retern ep.emit('error', err); - } - render(data); -}); - -ep.on('error', errorHandler); -``` - -We use `emitLater` in `db.check` to emit an event. Then whatever `db.check` do, we make sure events emit by `db.check` will catch by `ep`. And our code is easy to understand. -Also, we can use `doneLater` to simplify it just like what `ep.done()` do: - -```js -var ep = EventProxy.create(); - -db.check('key', ep.doneLater('check')); - -ep.once('check', function (permission) { - permission && db.get('key', ep.done('get')); -}); - -ep.once('get', function (data) { - render(data); -}); - -ep.fail(errorHandler); -``` -This is a kind of really simple and understandability code style. - -## Attentions -- Do not using `all` as event name in business. The event stays as reserved event. -- In exception handling part, please follow the best practice of Node(The first parameter of callback is exception). - -## [Contributors](https://github.com/JacksonTian/eventproxy/graphs/contributors) -Thanks to EventProxy users, enjoy using EventProxy, as well as feeding back much. - -```bash -project : eventproxy - repo age : 1 year, 10 months - active : 58 days - commits : 136 - files : 18 - authors : - 123 Jackson Tian 90.4% - 6 fengmk2 4.4% - 4 dead-horse 2.9% - 1 haoxin 0.7% - 1 redky 0.7% - 1 yaoazhen 0.7% - -``` - -## License - -[The MIT License](https://github.com/JacksonTian/eventproxy/blob/master/MIT-License). Please enjoy open source. diff --git a/disconf-web/html/tools/node_modules/eventproxy/component.json b/disconf-web/html/tools/node_modules/eventproxy/component.json deleted file mode 100644 index e5a273ffc..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/component.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "eventproxy", - "repo": "JacksonTian/eventproxy", - "description": "An implementation of task/event based asynchronous pattern.", - "version": "0.2.5", - "keywords": [ - "event", - "task-base", - "event machine", - "nested callback terminator" - ], - "dependencies": { - "visionmedia/debug": "*" - }, - "development": { - "chaijs/chai": "*", - "fengmk2/pedding": "*" - }, - "main": "index.js", - "scripts": ["index.js", "lib/eventproxy.js"], - "license": "MIT" -} diff --git a/disconf-web/html/tools/node_modules/eventproxy/index.js b/disconf-web/html/tools/node_modules/eventproxy/index.js deleted file mode 100644 index 490f48ff7..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/eventproxy'); diff --git a/disconf-web/html/tools/node_modules/eventproxy/lib/eventproxy.js b/disconf-web/html/tools/node_modules/eventproxy/lib/eventproxy.js deleted file mode 100644 index 63485aa28..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/lib/eventproxy.js +++ /dev/null @@ -1,586 +0,0 @@ -/*global define*/ -/*! - * This file is used for define the EventProxy library. - * @author Jackson Tian - * @version 0.2.2 - * ``` - */ -!(function (name, definition) { - // Check define - var hasDefine = typeof define === 'function', - // Check exports - hasExports = typeof module !== 'undefined' && module.exports; - - if (hasDefine) { - // AMD Module or CMD Module - define(definition); - } else if (hasExports) { - // Node.js Module - module.exports = definition(require('debug')('eventproxy')); - } else { - // Assign to common namespaces or simply the global object (window) - this[name] = definition(); - } -})('EventProxy', function (debug) { - debug = debug || function () {}; - - /** - * refs - */ - var SLICE = Array.prototype.slice; - var CONCAT = Array.prototype.concat; - - /** - * EventProxy. An implementation of task/event based asynchronous pattern. - * A module that can be mixed in to *any object* in order to provide it with custom events. - * You may `bind` or `unbind` a callback function to an event; - * `trigger`-ing an event fires all callbacks in succession. - * Examples: - * ```js - * var render = function (template, resources) {}; - * var proxy = new EventProxy(); - * proxy.assign("template", "l10n", render); - * proxy.trigger("template", template); - * proxy.trigger("l10n", resources); - * ``` - */ - var EventProxy = function () { - if (!(this instanceof EventProxy)) { - return new EventProxy(); - } - this._callbacks = {}; - this._fired = {}; - }; - - /** - * Bind an event, specified by a string name, `ev`, to a `callback` function. - * Passing `all` will bind the callback to all events fired. - * @param {String} eventName Event name. - * @param {Function} callback Callback. - */ - EventProxy.prototype.addListener = function (ev, callback) { - debug('Add listener for %s', ev); - this._callbacks[ev] = this._callbacks[ev] || []; - this._callbacks[ev].push(callback); - return this; - }; - /** - * `addListener` alias, `bind` - */ - EventProxy.prototype.bind = EventProxy.prototype.addListener; - /** - * `addListener` alias, `on` - */ - EventProxy.prototype.on = EventProxy.prototype.addListener; - /** - * `addListener` alias, `subscribe` - */ - EventProxy.prototype.subscribe = EventProxy.prototype.addListener; - - /** - * Bind an event, but put the callback into head of all callbacks. - * @param {String} eventName Event name. - * @param {Function} callback Callback. - */ - EventProxy.prototype.headbind = function (ev, callback) { - debug('Add listener for %s', ev); - this._callbacks[ev] = this._callbacks[ev] || []; - this._callbacks[ev].unshift(callback); - return this; - }; - /** - * Remove one or many callbacks. - * - * - If `callback` is null, removes all callbacks for the event. - * - If `eventName` is null, removes all bound callbacks for all events. - * @param {String} eventName Event name. - * @param {Function} callback Callback. - */ - EventProxy.prototype.removeListener = function (eventName, callback) { - var calls = this._callbacks; - if (!eventName) { - debug('Remove all listeners'); - this._callbacks = {}; - } else { - if (!callback) { - debug('Remove all listeners of %s', eventName); - calls[eventName] = []; - } else { - var list = calls[eventName]; - if (list) { - var l = list.length; - for (var i = 0; i < l; i++) { - if (callback === list[i]) { - debug('Remove a listener of %s', eventName); - list[i] = null; - break; - } - } - } - } - } - return this; - }; - /** - * `removeListener` alias, unbind - */ - EventProxy.prototype.unbind = EventProxy.prototype.removeListener; - - /** - * Remove all listeners. It equals unbind() - * Just add this API for as same as Event.Emitter. - * @param {String} event Event name. - */ - EventProxy.prototype.removeAllListeners = function (event) { - return this.unbind(event); - }; - - /** - * Trigger an event, firing all bound callbacks. Callbacks are passed the - * same arguments as `trigger` is, apart from the event name. - * Listening for `"all"` passes the true event name as the first argument. - * @param {String} eventName Event name - * @param {Mix} data Pass in data - */ - EventProxy.prototype.trigger = function (eventName, data) { - var list, ev, callback, args, i, l; - var both = 2; - var calls = this._callbacks; - debug('Emit event %s with data %j', eventName, data); - while (both--) { - ev = both ? eventName : 'all'; - list = calls[ev]; - if (list) { - for (i = 0, l = list.length; i < l; i++) { - if (!(callback = list[i])) { - list.splice(i, 1); - i--; - l--; - } else { - args = both ? SLICE.call(arguments, 1) : arguments; - callback.apply(this, args); - } - } - } - } - return this; - }; - /** - * `trigger` alias - */ - EventProxy.prototype.emit = EventProxy.prototype.trigger; - /** - * `trigger` alias - */ - EventProxy.prototype.fire = EventProxy.prototype.trigger; - - /** - * Bind an event like the bind method, but will remove the listener after it was fired. - * @param {String} ev Event name - * @param {Function} callback Callback - */ - EventProxy.prototype.once = function (ev, callback) { - var self = this; - var wrapper = function () { - callback.apply(self, arguments); - self.unbind(ev, wrapper); - }; - this.bind(ev, wrapper); - return this; - }; - - var later = typeof process !== 'undefined' && process.nextTick || function (fn) { - setTimeout(fn, 0); - }; - - /** - * emitLater - * make emit async - */ - EventProxy.prototype.emitLater = function () { - var self = this; - var args = arguments; - later(function () { - self.trigger.apply(self, args); - }); - }; - - /** - * Bind an event, and trigger it immediately. - * @param {String} ev Event name. - * @param {Function} callback Callback. - * @param {Mix} data The data that will be passed to calback as arguments. - */ - EventProxy.prototype.immediate = function (ev, callback, data) { - this.bind(ev, callback); - this.trigger(ev, data); - return this; - }; - /** - * `immediate` alias - */ - EventProxy.prototype.asap = EventProxy.prototype.immediate; - - var _assign = function (eventname1, eventname2, cb, once) { - var proxy = this; - var argsLength = arguments.length; - var times = 0; - var flag = {}; - - // Check the arguments length. - if (argsLength < 3) { - return this; - } - - var events = SLICE.call(arguments, 0, -2); - var callback = arguments[argsLength - 2]; - var isOnce = arguments[argsLength - 1]; - - // Check the callback type. - if (typeof callback !== "function") { - return this; - } - debug('Assign listener for events %j, once is %s', events, !!isOnce); - var bind = function (key) { - var method = isOnce ? "once" : "bind"; - proxy[method](key, function (data) { - proxy._fired[key] = proxy._fired[key] || {}; - proxy._fired[key].data = data; - if (!flag[key]) { - flag[key] = true; - times++; - } - }); - }; - - var length = events.length; - for (var index = 0; index < length; index++) { - bind(events[index]); - } - - var _all = function (event) { - if (times < length) { - return; - } - if (!flag[event]) { - return; - } - var data = []; - for (var index = 0; index < length; index++) { - data.push(proxy._fired[events[index]].data); - } - if (isOnce) { - proxy.unbind("all", _all); - } - debug('Events %j all emited with data %j', events, data); - callback.apply(null, data); - }; - proxy.bind("all", _all); - }; - - /** - * Assign some events, after all events were fired, the callback will be executed once. - * Examples: - * ```js - * proxy.all(ev1, ev2, callback); - * proxy.all([ev1, ev2], callback); - * proxy.all(ev1, [ev2, ev3], callback); - * ``` - * @param {String} eventName1 First event name. - * @param {String} eventName2 Second event name. - * @param {Function} callback Callback, that will be called after predefined events were fired. - */ - EventProxy.prototype.all = function (eventname1, eventname2, callback) { - var args = CONCAT.apply([], arguments); - args.push(true); - _assign.apply(this, args); - return this; - }; - /** - * `all` alias - */ - EventProxy.prototype.assign = EventProxy.prototype.all; - - /** - * Assign the only one 'error' event handler. - * @param {Function(err)} callback - */ - EventProxy.prototype.fail = function (callback) { - var that = this; - that.once('error', function (err) { - that.unbind(); - // put all arguments to the error handler - // fail(function(err, args1, args2, ...){}) - callback.apply(null, arguments); - }); - return this; - }; - - /** - * Assign some events, after all events were fired, the callback will be executed first time. - * Then any event that predefined be fired again, the callback will executed with the newest data. - * Examples: - * ```js - * proxy.tail(ev1, ev2, callback); - * proxy.tail([ev1, ev2], callback); - * proxy.tail(ev1, [ev2, ev3], callback); - * ``` - * @param {String} eventName1 First event name. - * @param {String} eventName2 Second event name. - * @param {Function} callback Callback, that will be called after predefined events were fired. - */ - EventProxy.prototype.tail = function () { - var args = CONCAT.apply([], arguments); - args.push(false); - _assign.apply(this, args); - return this; - }; - /** - * `tail` alias, assignAll - */ - EventProxy.prototype.assignAll = EventProxy.prototype.tail; - /** - * `tail` alias, assignAlways - */ - EventProxy.prototype.assignAlways = EventProxy.prototype.tail; - - /** - * The callback will be executed after the event be fired N times. - * @param {String} eventName Event name. - * @param {Number} times N times. - * @param {Function} callback Callback, that will be called after event was fired N times. - */ - EventProxy.prototype.after = function (eventName, times, callback) { - if (times === 0) { - callback.call(null, []); - return this; - } - var proxy = this, - firedData = []; - this._after = this._after || {}; - var group = eventName + '_group'; - this._after[group] = { - index: 0, - results: [] - }; - debug('After emit %s times, event %s\'s listenner will execute', times, eventName); - var all = function (name, data) { - if (name === eventName) { - times--; - firedData.push(data); - if (times < 1) { - debug('Event %s was emit %s, and execute the listenner', eventName, times); - proxy.unbind("all", all); - callback.apply(null, [firedData]); - } - } - if (name === group) { - times--; - proxy._after[group].results[data.index] = data.result; - if (times < 1) { - debug('Event %s was emit %s, and execute the listenner', eventName, times); - proxy.unbind("all", all); - callback.call(null, proxy._after[group].results); - } - } - }; - proxy.bind("all", all); - return this; - }; - - /** - * The `after` method's helper. Use it will return ordered results. - * If you need manipulate result, you need callback - * Examples: - * ```js - * var ep = new EventProxy(); - * ep.after('file', files.length, function (list) { - * // Ordered results - * }); - * for (var i = 0; i < files.length; i++) { - * fs.readFile(files[i], 'utf-8', ep.group('file')); - * } - * ``` - * @param {String} eventName Event name, shoule keep consistent with `after`. - * @param {Function} callback Callback function, should return the final result. - */ - EventProxy.prototype.group = function (eventName, callback) { - var that = this; - var group = eventName + '_group'; - var index = that._after[group].index; - that._after[group].index++; - return function (err, data) { - if (err) { - // put all arguments to the error handler - return that.emit.apply(that, ['error'].concat(SLICE.call(arguments))); - } - that.emit(group, { - index: index, - // callback(err, args1, args2, ...) - result: callback ? callback.apply(null, SLICE.call(arguments, 1)) : data - }); - }; - }; - - /** - * The callback will be executed after any registered event was fired. It only executed once. - * @param {String} eventName1 Event name. - * @param {String} eventName2 Event name. - * @param {Function} callback The callback will get a map that has data and eventName attributes. - */ - EventProxy.prototype.any = function () { - var proxy = this, - callback = arguments[arguments.length - 1], - events = SLICE.call(arguments, 0, -1), - _eventName = events.join("_"); - - debug('Add listenner for Any of events %j emit', events); - proxy.once(_eventName, callback); - - var _bind = function (key) { - proxy.bind(key, function (data) { - debug('One of events %j emited, execute the listenner'); - proxy.trigger(_eventName, {"data": data, eventName: key}); - }); - }; - - for (var index = 0; index < events.length; index++) { - _bind(events[index]); - } - }; - - /** - * The callback will be executed when the event name not equals with assigned event. - * @param {String} eventName Event name. - * @param {Function} callback Callback. - */ - EventProxy.prototype.not = function (eventName, callback) { - var proxy = this; - debug('Add listenner for not event %s', eventName); - proxy.bind("all", function (name, data) { - if (name !== eventName) { - debug('listenner execute of event %s emit, but not event %s.', name, eventName); - callback(data); - } - }); - }; - - /** - * Success callback wrapper, will handler err for you. - * - * ```js - * fs.readFile('foo.txt', ep.done('content')); - * - * // equal to => - * - * fs.readFile('foo.txt', function (err, content) { - * if (err) { - * return ep.emit('error', err); - * } - * ep.emit('content', content); - * }); - * ``` - * - * ```js - * fs.readFile('foo.txt', ep.done('content', function (content) { - * return content.trim(); - * })); - * - * // equal to => - * - * fs.readFile('foo.txt', function (err, content) { - * if (err) { - * return ep.emit('error', err); - * } - * ep.emit('content', content.trim()); - * }); - * ``` - * @param {Function|String} handler, success callback or event name will be emit after callback. - * @return {Function} - */ - EventProxy.prototype.done = function (handler, callback) { - var that = this; - return function (err, data) { - if (err) { - // put all arguments to the error handler - return that.emit.apply(that, ['error'].concat(SLICE.call(arguments))); - } - - // callback(err, args1, args2, ...) - var args = SLICE.call(arguments, 1); - - if (typeof handler === 'string') { - // getAsync(query, ep.done('query')); - // or - // getAsync(query, ep.done('query', function (data) { - // return data.trim(); - // })); - if (callback) { - // only replace the args when it really return a result - return that.emit(handler, callback.apply(null, args)); - } else { - // put all arguments to the done handler - //ep.done('some'); - //ep.on('some', function(args1, args2, ...){}); - return that.emit.apply(that, [handler].concat(args)); - } - } - - // speed improve for mostly case: `callback(err, data)` - if (arguments.length <= 2) { - return handler(data); - } - - // callback(err, args1, args2, ...) - handler.apply(null, args); - }; - }; - - /** - * make done async - */ - EventProxy.prototype.doneLater = function (handler, callback) { - var _doneHandler = this.done(handler, callback); - return function (err, data) { - var args = arguments; - later(function () { - _doneHandler.apply(null, args); - }); - }; - }; - - /** - * Create a new EventProxy - * Examples: - * ```js - * var ep = EventProxy.create(); - * ep.assign('user', 'articles', function(user, articles) { - * // do something... - * }); - * // or one line ways: Create EventProxy and Assign - * var ep = EventProxy.create('user', 'articles', function(user, articles) { - * // do something... - * }); - * ``` - * @returns {EventProxy} EventProxy instance - */ - EventProxy.create = function () { - var ep = new EventProxy(); - var args = CONCAT.apply([], arguments); - if (args.length) { - var errorHandler = args[args.length - 1]; - var callback = args[args.length - 2]; - if (typeof errorHandler === 'function' && typeof callback === 'function') { - args.pop(); - ep.fail(errorHandler); - } - ep.assign.apply(ep, args); - } - return ep; - }; - - // Backwards compatibility - EventProxy.EventProxy = EventProxy; - - return EventProxy; -}); diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/.npmignore b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/.npmignore deleted file mode 100644 index f1250e584..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -support -test -examples -*.sock diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/History.md b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/History.md deleted file mode 100644 index f023269be..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/History.md +++ /dev/null @@ -1,62 +0,0 @@ - -0.7.2 / 2013-02-06 -================== - - * fix package.json - * fix: Mobile Safari (private mode) is broken with debug - * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript - -0.7.1 / 2013-02-05 -================== - - * add repository URL to package.json - * add DEBUG_COLORED to force colored output - * add browserify support - * fix component. Closes #24 - -0.7.0 / 2012-05-04 -================== - - * Added .component to package.json - * Added debug.component.js build - -0.6.0 / 2012-03-16 -================== - - * Added support for "-" prefix in DEBUG [Vinay Pulim] - * Added `.enabled` flag to the node version [TooTallNate] - -0.5.0 / 2012-02-02 -================== - - * Added: humanize diffs. Closes #8 - * Added `debug.disable()` to the CS variant - * Removed padding. Closes #10 - * Fixed: persist client-side variant again. Closes #9 - -0.4.0 / 2012-02-01 -================== - - * Added browser variant support for older browsers [TooTallNate] - * Added `debug.enable('project:*')` to browser variant [TooTallNate] - * Added padding to diff (moved it to the right) - -0.3.0 / 2012-01-26 -================== - - * Added millisecond diff when isatty, otherwise UTC string - -0.2.0 / 2012-01-22 -================== - - * Added wildcard support - -0.1.0 / 2011-12-02 -================== - - * Added: remove colors unless stderr isatty [TooTallNate] - -0.0.1 / 2010-01-03 -================== - - * Initial release diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/Readme.md b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/Readme.md deleted file mode 100644 index 15ee50193..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/Readme.md +++ /dev/null @@ -1,115 +0,0 @@ - -# debug - - tiny node.js debugging utility modelled after node core's debugging technique. - -## Installation - -``` -$ npm install debug -``` - -## Usage - - With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility. - -Example _app.js_: - -```js -var debug = require('debug')('http') - , http = require('http') - , name = 'My App'; - -// fake app - -debug('booting %s', name); - -http.createServer(function(req, res){ - debug(req.method + ' ' + req.url); - res.end('hello\n'); -}).listen(3000, function(){ - debug('listening'); -}); - -// fake worker of some kind - -require('./worker'); -``` - -Example _worker.js_: - -```js -var debug = require('debug')('worker'); - -setInterval(function(){ - debug('doing some work'); -}, 1000); -``` - - The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: - - ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png) - - ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png) - -## Millisecond diff - - When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. - - ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png) - - When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: - - ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png) - -## Conventions - - If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". - -## Wildcards - - The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. - - You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:". - -## Browser support - - Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. - -```js -a = debug('worker:a'); -b = debug('worker:b'); - -setInterval(function(){ - a('doing some work'); -}, 1000); - -setInterval(function(){ - a('doing some work'); -}, 1200); -``` - -## License - -(The MIT License) - -Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> - -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. \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/component.json b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/component.json deleted file mode 100644 index 4ad09718e..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/component.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "debug", - "repo": "visionmedia/debug", - "description": "small debugging utility", - "version": "0.7.2", - "keywords": ["debug", "log", "debugger"], - "scripts": ["index.js", "debug.js"], - "dependencies": {} -} diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/debug.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/debug.js deleted file mode 100644 index e47ba5b08..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/debug.js +++ /dev/null @@ -1,124 +0,0 @@ - -/** - * Expose `debug()` as the module. - */ - -module.exports = debug; - -/** - * Create a debugger with the given `name`. - * - * @param {String} name - * @return {Type} - * @api public - */ - -function debug(name) { - if (!debug.enabled(name)) return function(){}; - - return function(fmt){ - var curr = new Date; - var ms = curr - (debug[name] || curr); - debug[name] = curr; - - fmt = name - + ' ' - + fmt - + ' +' + debug.humanize(ms); - - // This hackery is required for IE8 - // where `console.log` doesn't have 'apply' - window.console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); - } -} - -/** - * The currently active debug mode names. - */ - -debug.names = []; -debug.skips = []; - -/** - * Enables a debug mode by name. This can include modes - * separated by a colon and wildcards. - * - * @param {String} name - * @api public - */ - -debug.enable = function(name) { - try { - localStorage.debug = name; - } catch(e){} - - var split = (name || '').split(/[\s,]+/) - , len = split.length; - - for (var i = 0; i < len; i++) { - name = split[i].replace('*', '.*?'); - if (name[0] === '-') { - debug.skips.push(new RegExp('^' + name.substr(1) + '$')); - } - else { - debug.names.push(new RegExp('^' + name + '$')); - } - } -}; - -/** - * Disable debug output. - * - * @api public - */ - -debug.disable = function(){ - debug.enable(''); -}; - -/** - * Humanize the given `ms`. - * - * @param {Number} m - * @return {String} - * @api private - */ - -debug.humanize = function(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; - - if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; - if (ms >= min) return (ms / min).toFixed(1) + 'm'; - if (ms >= sec) return (ms / sec | 0) + 's'; - return ms + 'ms'; -}; - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -debug.enabled = function(name) { - for (var i = 0, len = debug.skips.length; i < len; i++) { - if (debug.skips[i].test(name)) { - return false; - } - } - for (var i = 0, len = debug.names.length; i < len; i++) { - if (debug.names[i].test(name)) { - return true; - } - } - return false; -}; - -// persist - -if (window.localStorage) debug.enable(localStorage.debug); diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/app.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/app.js deleted file mode 100644 index 05374d98d..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/app.js +++ /dev/null @@ -1,19 +0,0 @@ - -var debug = require('../')('http') - , http = require('http') - , name = 'My App'; - -// fake app - -debug('booting %s', name); - -http.createServer(function(req, res){ - debug(req.method + ' ' + req.url); - res.end('hello\n'); -}).listen(3000, function(){ - debug('listening'); -}); - -// fake worker of some kind - -require('./worker'); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/browser.html b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/browser.html deleted file mode 100644 index 7510eee7b..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/browser.html +++ /dev/null @@ -1,24 +0,0 @@ - - - debug() - - - - - - - diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/wildcards.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/wildcards.js deleted file mode 100644 index 1fdac20a9..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/wildcards.js +++ /dev/null @@ -1,10 +0,0 @@ - -var debug = { - foo: require('../')('test:foo'), - bar: require('../')('test:bar'), - baz: require('../')('test:baz') -}; - -debug.foo('foo') -debug.bar('bar') -debug.baz('baz') \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/worker.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/worker.js deleted file mode 100644 index 7f6d2886c..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/example/worker.js +++ /dev/null @@ -1,22 +0,0 @@ - -// DEBUG=* node example/worker -// DEBUG=worker:* node example/worker -// DEBUG=worker:a node example/worker -// DEBUG=worker:b node example/worker - -var a = require('../')('worker:a') - , b = require('../')('worker:b'); - -function work() { - a('doing lots of uninteresting work'); - setTimeout(work, Math.random() * 1000); -} - -work(); - -function workb() { - b('doing some work'); - setTimeout(workb, Math.random() * 2000); -} - -workb(); \ No newline at end of file diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/index.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/index.js deleted file mode 100644 index e02c13b7f..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/index.js +++ /dev/null @@ -1,5 +0,0 @@ -if ('undefined' == typeof window) { - module.exports = require('./lib/debug'); -} else { - module.exports = require('./debug'); -} diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/lib/debug.js b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/lib/debug.js deleted file mode 100644 index 0b07aa1d1..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/lib/debug.js +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Module dependencies. - */ - -var tty = require('tty'); - -/** - * Expose `debug()` as the module. - */ - -module.exports = debug; - -/** - * Enabled debuggers. - */ - -var names = [] - , skips = []; - -(process.env.DEBUG || '') - .split(/[\s,]+/) - .forEach(function(name){ - name = name.replace('*', '.*?'); - if (name[0] === '-') { - skips.push(new RegExp('^' + name.substr(1) + '$')); - } else { - names.push(new RegExp('^' + name + '$')); - } - }); - -/** - * Colors. - */ - -var colors = [6, 2, 3, 4, 5, 1]; - -/** - * Previous debug() call. - */ - -var prev = {}; - -/** - * Previously assigned color. - */ - -var prevColor = 0; - -/** - * Is stdout a TTY? Colored output is disabled when `true`. - */ - -var isatty = tty.isatty(2); - -/** - * Select a color. - * - * @return {Number} - * @api private - */ - -function color() { - return colors[prevColor++ % colors.length]; -} - -/** - * Humanize the given `ms`. - * - * @param {Number} m - * @return {String} - * @api private - */ - -function humanize(ms) { - var sec = 1000 - , min = 60 * 1000 - , hour = 60 * min; - - if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; - if (ms >= min) return (ms / min).toFixed(1) + 'm'; - if (ms >= sec) return (ms / sec | 0) + 's'; - return ms + 'ms'; -} - -/** - * Create a debugger with the given `name`. - * - * @param {String} name - * @return {Type} - * @api public - */ - -function debug(name) { - function disabled(){} - disabled.enabled = false; - - var match = skips.some(function(re){ - return re.test(name); - }); - - if (match) return disabled; - - match = names.some(function(re){ - return re.test(name); - }); - - if (!match) return disabled; - var c = color(); - - function colored(fmt) { - var curr = new Date; - var ms = curr - (prev[name] || curr); - prev[name] = curr; - - fmt = ' \u001b[9' + c + 'm' + name + ' ' - + '\u001b[3' + c + 'm\u001b[90m' - + fmt + '\u001b[3' + c + 'm' - + ' +' + humanize(ms) + '\u001b[0m'; - - console.error.apply(this, arguments); - } - - function plain(fmt) { - fmt = new Date().toUTCString() - + ' ' + name + ' ' + fmt; - console.error.apply(this, arguments); - } - - colored.enabled = plain.enabled = true; - - return isatty || process.env.DEBUG_COLORS - ? colored - : plain; -} diff --git a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/package.json b/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/package.json deleted file mode 100644 index 7b2911336..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/node_modules/debug/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "debug", - "version": "0.7.2", - "repository": { - "type": "git", - "url": "git://github.com/visionmedia/debug.git" - }, - "description": "small debugging utility", - "keywords": [ - "debug", - "log", - "debugger" - ], - "author": { - "name": "TJ Holowaychuk", - "email": "tj@vision-media.ca" - }, - "dependencies": {}, - "devDependencies": { - "mocha": "*" - }, - "main": "lib/debug.js", - "browserify": "debug.js", - "engines": { - "node": "*" - }, - "component": { - "scripts": { - "debug/index.js": "index.js", - "debug/debug.js": "debug.js" - } - }, - "readme": "\n# debug\n\n tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n , http = require('http')\n , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n debug(req.method + ' ' + req.url);\n res.end('hello\\n');\n}).listen(3000, function(){\n debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n \n ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n You can also exclude specific debuggers by prefixing them with a \"-\" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", - "readmeFilename": "Readme.md", - "bugs": { - "url": "https://github.com/visionmedia/debug/issues" - }, - "homepage": "https://github.com/visionmedia/debug", - "_id": "debug@0.7.2", - "_from": "debug@0.7.2" -} diff --git a/disconf-web/html/tools/node_modules/eventproxy/package.json b/disconf-web/html/tools/node_modules/eventproxy/package.json deleted file mode 100644 index ce65c2f62..000000000 --- a/disconf-web/html/tools/node_modules/eventproxy/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "eventproxy", - "description": "An implementation of task/event based asynchronous pattern.", - "homepage": "https://github.com/JacksonTian/eventproxy", - "keywords": [ - "event", - "task-base", - "event machine", - "nested callback terminator" - ], - "author": { - "name": "Jackson Tian", - "email": "shyvo1987@gmail.com" - }, - "contributors": [ - { - "name": "Jackson Tian", - "email": "shyvo1987@gmail.com" - }, - { - "name": "fengmk2", - "email": "fengmk2@gmail.com" - } - ], - "dependencies": { - "debug": "0.7.2" - }, - "devDependencies": { - "mocha": "*", - "mocha-phantomjs": "*", - "component": "*", - "blanket": "*", - "pedding": "*", - "chai": "*", - "travis-cov": "*" - }, - "scripts": { - "test": "make test-all" - }, - "config": { - "blanket": { - "pattern": "eventproxy/lib", - "data-cover-flags": { - "debug": false - } - }, - "travis-cov": { - "threshold": 97 - } - }, - "repository": { - "type": "git", - "url": "git://github.com/JacksonTian/eventproxy.git" - }, - "version": "0.2.7", - "main": "index.js", - "directories": { - "doc": "doc", - "test": "test" - }, - "license": "MIT", - "readme": "EventProxy [![Build Status](https://secure.travis-ci.org/JacksonTian/eventproxy.png)](http://travis-ci.org/JacksonTian/eventproxy) [![NPM version](https://badge.fury.io/js/eventproxy.png)](http://badge.fury.io/js/eventproxy) [English Doc](https://github.com/JacksonTian/eventproxy/blob/master/README_en.md)\n======\n\n> 这个世界上不存在所谓回调函数深度嵌套的问题。 —— [Jackson Tian](http://weibo.com/shyvo)\n\n> 世界上本没有嵌套回调,写得人多了,也便有了`}}}}}}}}}}}}`。 —— [fengmk2](http://fengmk2.github.com)\n\n* API文档: [API Documentation](http://html5ify.com/eventproxy/api.html)\n* jscoverage: [97%](http://html5ify.com/eventproxy/coverage.html)\n* 源码注解:[注解文档](http://html5ify.com/eventproxy/eventproxy.html)\n\n\nEventProxy 仅仅是一个很轻量的工具,但是能够带来一种事件式编程的思维变化。有几个特点:\n\n1. 利用事件机制解耦复杂业务逻辑\n2. 移除被广为诟病的深度callback嵌套问题\n3. 将串行等待变成并行等待,提升多异步协作场景下的执行效率\n4. 友好的Error handling\n5. 无平台依赖,适合前后端,能用于浏览器和Node.js\n6. 兼容CMD,AMD以及CommonJS模块环境\n\n现在的,无深度嵌套的,并行的\n\n```js\nvar ep = EventProxy.create(\"template\", \"data\", \"l10n\", function (template, data, l10n) {\n _.template(template, data, l10n);\n});\n\n$.get(\"template\", function (template) {\n // something\n ep.emit(\"template\", template);\n});\n$.get(\"data\", function (data) {\n // something\n ep.emit(\"data\", data);\n});\n$.get(\"l10n\", function (l10n) {\n // something\n ep.emit(\"l10n\", l10n);\n});\n```\n\n过去的,深度嵌套的,串行的。\n\n```js\nvar render = function (template, data) {\n _.template(template, data);\n};\n$.get(\"template\", function (template) {\n // something\n $.get(\"data\", function (data) {\n // something\n $.get(\"l10n\", function (l10n) {\n // something\n render(template, data, l10n);\n });\n });\n});\n```\n## 安装\n### Node用户\n通过NPM安装即可使用:\n\n```bash\n$ npm install eventproxy\n```\n\n调用:\n\n```js\nvar EventProxy = require('eventproxy');\n```\n\n### Component\n\n```bash\n$ component install JacksonTian/eventproxy\n```\n\n### 前端用户\n以下示例均指向Github的源文件地址,您也可以[下载源文件](https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy.js)到你自己的项目中。整个文件注释全面,带注释和空行,一共约500行。为保证EventProxy的易嵌入,项目暂不提供压缩版。用户可以自行采用Uglify、YUI Compressor或Google Closure Complier进行压缩。\n\n#### 普通环境\n在页面中嵌入脚本即可使用:\n\n```html\n\n```\n使用:\n\n```js\n// EventProxy此时是一个全局变量\nvar ep = new EventProxy();\n```\n\n#### SeaJS用户\nSeaJS下只需配置别名,然后`require`引用即可使用。\n\n```js\n// 配置\nseajs.config({\n alias: {\n eventproxy: 'https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy.js'\n }\n});\n// 使用\nseajs.use(['eventproxy'], function (EventProxy) {\n // TODO\n});\n// 或者\ndefine('test', function (require, exports, modules) {\n var EventProxy = require('eventproxy');\n});\n```\n\n#### RequireJS用户\nRequireJS实现的是AMD规范。\n\n```js\n// 配置路径\nrequire.config({\n paths: {\n eventproxy: \"https://raw.github.com/JacksonTian/eventproxy/master/lib/eventproxy\"\n }\n});\n// 使用\nrequire([\"eventproxy\"], function (EventProxy) {\n // TODO\n});\n```\n## 异步协作\n### 多类型异步协作\n此处以页面渲染为场景,渲染页面需要模板、数据。假设都需要异步读取。\n\n```js\nvar ep = new EventProxy();\nep.all('tpl', 'data', function (tpl, data) {\n // 在所有指定的事件触发后,将会被调用执行\n // 参数对应各自的事件名\n});\nfs.readFile('template.tpl', 'utf-8', function (err, content) {\n ep.emit('tpl', content);\n});\ndb.get('some sql', function (err, result) {\n ep.emit('data', result);\n});\n```\n\n`all`方法将handler注册到事件组合上。当注册的多个事件都触发后,将会调用handler执行,每个事件传递的数据,将会依照事件名顺序,传入handler作为参数。\n#### 快速创建\nEventProxy提供了`create`静态方法,可以快速完成注册`all`事件。\n\n```js\nvar ep = EventProxy.create('tpl', 'data', function (tpl, data) {\n // TODO\n});\n```\n\n以上方法等效于\n\n```js\nvar ep = new EventProxy();\nep.all('tpl', 'data', function (tpl, data) {\n // TODO\n});\n```\n\n### 重复异步协作\n此处以读取目录下的所有文件为例,在异步操作中,我们需要在所有异步调用结束后,执行某些操作。\n\n```js\nvar ep = new EventProxy();\nep.after('got_file', files.length, function (list) {\n // 在所有文件的异步执行结束后将被执行\n // 所有文件的内容都存在list数组中\n});\nfor (var i = 0; i < files.length; i++) {\n fs.readFile(files[i], 'utf-8', function (err, content) {\n // 触发结果事件\n ep.emit('got_file', content);\n });\n}\n```\n\n`after`方法适合重复的操作,比如读取10个文件,调用5次数据库等。将handler注册到N次相同事件的触发上。达到指定的触发数,handler将会被调用执行,每次触发的数据,将会按触发顺序,存为数组作为参数传入。\n\n### 持续型异步协作\n此处以股票为例,数据和模板都是异步获取,但是数据会持续刷新,视图会需要重新刷新。\n\n```js\nvar ep = new EventProxy();\nep.tail('tpl', 'data', function (tpl, data) {\n // 在所有指定的事件触发后,将会被调用执行\n // 参数对应各自的事件名的最新数据\n});\nfs.readFile('template.tpl', 'utf-8', function (err, content) {\n ep.emit('tpl', content);\n});\nsetInterval(function () {\n db.get('some sql', function (err, result) {\n ep.emit('data', result);\n });\n}, 2000);\n```\n\n`tail`与`all`方法比较类似,都是注册到事件组合上。不同在于,指定事件都触发之后,如果事件依旧持续触发,将会在每次触发时调用handler,极像一条尾巴。\n\n\n## 基本事件\n通过事件实现异步协作是EventProxy的主要亮点。除此之外,它还是一个基本的事件库。携带如下基本API\n\n- `on`/`addListener`,绑定事件监听器\n- `emit`,触发事件\n- `once`,绑定只执行一次的事件监听器\n- `removeListener`,移除事件的监听器\n- `removeAllListeners`,移除单个事件或者所有事件的监听器\n\n为了照顾各个环境的开发者,上面的方法多具有别名。\n\n- YUI3使用者,`subscribe`和`fire`你应该知道分别对应的是`on`/`addListener`和`emit`。\n- jQuery使用者,`trigger`对应的方法是`emit`,`bind`对应的就是`on`/`addListener`。\n- `removeListener`和`removeAllListeners`其实都可以通过别名`unbind`完成。\n\n所以在你的环境下,选用你喜欢的API即可。\n\n更多API的描述请访问[API Docs](http://html5ify.com/eventproxy/api.html)。\n\n## 异常处理\n在异步方法中,实际上,异常处理需要占用一定比例的精力。在过去一段时间内,我们都是通过额外添加`error`事件来进行处理的,代码大致如下:\n\n```js\nexports.getContent = function (callback) {\n var ep = new EventProxy();\n ep.all('tpl', 'data', function (tpl, data) {\n // 成功回调\n callback(null, {\n template: tpl,\n data: data\n });\n });\n // 侦听error事件\n ep.bind('error', function (err) {\n // 卸载掉所有handler\n ep.unbind();\n // 异常回调\n callback(err);\n });\n fs.readFile('template.tpl', 'utf-8', function (err, content) {\n if (err) {\n // 一旦发生异常,一律交给error事件的handler处理\n return ep.emit('error', err);\n }\n ep.emit('tpl', content);\n });\n db.get('some sql', function (err, result) {\n if (err) {\n // 一旦发生异常,一律交给error事件的handler处理\n return ep.emit('error', err);\n }\n ep.emit('data', result);\n });\n};\n```\n\n代码量因为异常的处理,一下子上去了很多。在这里EventProxy经过很多实践后,我们根据我们的最佳实践提供了优化的错误处理方案。\n\n```js\nexports.getContent = function (callback) {\n var ep = new EventProxy();\n ep.all('tpl', 'data', function (tpl, data) {\n // 成功回调\n callback(null, {\n template: tpl,\n data: data\n });\n });\n // 添加error handler\n ep.fail(callback);\n\n fs.readFile('template.tpl', 'utf-8', ep.done('tpl'));\n db.get('some sql', ep.done('data'));\n};\n```\n\n上述代码优化之后,业务开发者几乎不用关心异常处理了。代码量降低效果明显。 \n这里代码的转换,也许有开发者并不放心。其实秘诀在`fail`方法和`done`方法中。\n\n### 神奇的fail\n\n```js\nep.fail(callback);\n// 由于参数位相同,它实际是\nep.fail(function (err) {\n callback(err);\n});\n\n// 等价于\nep.bind('error', function (err) {\n // 卸载掉所有handler\n ep.unbind();\n // 异常回调\n callback(err);\n});\n```\n\n`fail`方法侦听了`error`事件,默认处理卸载掉所有handler,并调用回调函数。\n\n### 神奇的done\n\n```js\nep.done('tpl');\n// 等价于\nfunction (err, content) {\n if (err) {\n // 一旦发生异常,一律交给error事件的handler处理\n return ep.emit('error', err);\n }\n ep.emit('tpl', content);\n}\n```\n\n在Node的最佳实践中,回调函数第一个参数一定会是一个`error`对象。检测到异常后,将会触发`error`事件。剩下的参数,将触发事件,传递给对应handler处理。\n\n#### done也接受回调函数\n`done`方法除了接受事件名外,还接受回调函数。如果是函数时,它将剔除第一个`error`对象(此时为`null`)后剩余的参数,传递给该回调函数作为参数。该回调函数无需考虑异常处理。\n\n```js\nep.done(function (content) {\n // 这里无需考虑异常\n // 手工emit\n ep.emit('someevent', newcontent);\n});\n```\n\n当然手工emit的方式并不太好,我们更进一步的版本:\n\n```js\nep.done('tpl', function (tpl) {\n // 将内容更改后,返回即可\n return tpl.trim();\n});\n```\n\n#### 注意事项\n如果`emit`需要传递多个参数时,`ep.done(event, fn)`的方式不能满足需求,还是需要`ep.done(fn)`,进行手工`emit`多个参数。\n\n### 神奇的group\n`fail`除了用于协助`all`方法完成外,也能协助`after`中的异常处理。另外,在`after`的回调函数中,结果顺序是与用户`emit`的顺序有关。为了满足返回数据按发起异步调用的顺序排列,`EventProxy`提供了`group`方法。\n\n```js\nvar ep = new EventProxy();\nep.after('got_file', files.length, function (list) {\n // 在所有文件的异步执行结束后将被执行\n // 所有文件的内容都存在list数组中,按顺序排列\n});\nfor (var i = 0; i < files.length; i++) {\n fs.readFile(files[i], 'utf-8', ep.group('got_file'));\n}\n```\n`group`秉承`done`函数的设计,它包含异常的传递。同时它还隐含了对返回数据进行编号,在结束时,按顺序返回。\n\n```js\nep.group('got_file');\n// 约等价于\nfunction (err, data) {\n if (err) {\n return ep.emit('error', err);\n }\n ep.emit('got_file', data);\n};\n```\n\n当回调函数的数据还需要进行加工时,可以给`group`带上回调函数,只要在操作后将数据返回即可:\n\n```js\nep.group('got_file', function (data) {\n // some code\n return data;\n});\n```\n\n### 异步事件触发: emitLater && doneLater\n\n在node中,`emit`方法是同步的,EventProxy中的`emit`,`trigger`等跟node的风格一致,也是同步的。看下面这段代码,可能眼尖的同学一下就发现了隐藏的bug: \n```js\nvar ep = EventProxy.create();\n\ndb.check('key', function (err, permission) {\n if (err) {\n return ep.emit('error', err);\n }\n ep.emit('check', permission);\n});\n\nep.once('check', function (permission) {\n permission && db.get('key', function (err, data) {\n if (err) {\n return ep.emit('error');\n }\n ep.emit('get', data);\n });\n});\n\nep.once('get', function (err, data) {\n if (err) {\n retern ep.emit('error', err);\n }\n render(data);\n});\n\nep.on('error', errorHandler);\n```\n\n没错,万一`db.check`的`callback`被同步执行了,在`ep`监听`check`事件之前,它就已经被抛出来了,后续逻辑没办法继续执行。尽管node的约定是所有的`callback`都是需要异步返回的,但是如果这个方法是由第三方提供的,我们没有办法保证`db.check`的`callback`一定会异步执行,所以我们的代码通常就变成了这样: \n\n```js\nvar ep = EventProxy.create();\n\nep.once('check', function (permission) {\n permission && db.get('key', function (err, data) {\n if (err) {\n return ep.emit('error');\n }\n ep.emit('get', data);\n });\n});\n\nep.once('get', function (err, data) {\n if (err) {\n retern ep.emit('error', err);\n }\n render(data);\n});\n\nep.on('error', errorHandler);\n\ndb.check('key', function (err, permission) {\n if (err) {\n return ep.emit('error', err);\n }\n ep.emit('check', permission);\n});\n```\n我们被迫把`db.check`挪到最后,保证事件先被监听,再执行`db.check`。`check`->`get`->`render`的逻辑,在代码中看起来变成了`get`->`render`->`check`。如果整个逻辑更加复杂,这种风格将会让代码很难读懂。 \n\n这时候,我们需要的就是 __异步事件触发__: \n\n```js\nvar ep = EventProxy.create();\n\ndb.check('key', function (err, permission) {\n if (err) {\n return ep.emitLater('error', err);\n }\n ep.emitLater('check', permission);\n});\n\nep.once('check', function (permission) {\n permission && db.get('key', function (err, data) {\n if (err) {\n return ep.emit('error');\n }\n ep.emit('get', data);\n });\n});\n\nep.once('get', function (err, data) {\n if (err) {\n retern ep.emit('error', err);\n }\n render(data);\n});\n\nep.on('error', errorHandler);\n```\n上面代码中,我们把`db.check`的回调函数中的事件通过`emitLater`触发,这样,就算`db.check`的回调函数被同步执行了,事件的触发也还是异步的,`ep`在当前事件循环中监听了所有的事件,之后的事件循环中才会去触发`check`事件。代码顺序将和逻辑顺序保持一致。 \n当然,这么复杂的代码,必须可以像`ep.done()`一样通过`doneLater`来解决: \n\n```js\nvar ep = EventProxy.create();\n\ndb.check('key', ep.doneLater('check'));\n\nep.once('check', function (permission) {\n permission && db.get('key', ep.done('get'));\n});\n\nep.once('get', function (data) {\n render(data);\n});\n\nep.fail(errorHandler);\n```\n最终呈现出来的,是一段简洁且清晰的代码。 \n\n\n## 注意事项\n- 请勿使用`all`作为业务中的事件名。该事件名为保留事件。\n- 异常处理部分,请遵循Node的最佳实践(回调函数首个参数为异常传递位)。\n\n## [贡献者们](https://github.com/JacksonTian/eventproxy/graphs/contributors)\n谢谢EventProxy的使用者们,享受EventProxy的过程,也给EventProxy回馈良多。\n\n```bash\n project : eventproxy\n repo age : 1 year, 10 months\n active : 58 days\n commits : 136\n files : 18\n authors : \n 123 Jackson Tian 90.4%\n 6 fengmk2 4.4%\n 4 dead-horse 2.9%\n 1 haoxin 0.7%\n 1 redky 0.7%\n 1 yaoazhen 0.7%\n\n```\n\n## License \n\n[The MIT License](https://github.com/JacksonTian/eventproxy/blob/master/MIT-License)。请自由享受开源。\n\n## 捐赠\n如果您觉得本模块对您有帮助,欢迎请作者一杯咖啡\n\n[![捐赠EventProxy](https://img.alipay.com/sys/personalprod/style/mc/btn-index.png)](https://me.alipay.com/jacksontian)\n\n\n[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/JacksonTian/eventproxy/trend.png)](https://bitdeli.com/free \"Bitdeli Badge\")\n\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/JacksonTian/eventproxy/issues" - }, - "_id": "eventproxy@0.2.7", - "_from": "eventproxy@" -} diff --git a/disconf-web/html/tools/parse.js b/disconf-web/html/tools/parse.js deleted file mode 100644 index 90becce16..000000000 --- a/disconf-web/html/tools/parse.js +++ /dev/null @@ -1,91 +0,0 @@ -var fs = require('fs'); -var ejs = require('ejs'); -var EventProxy = require('eventproxy'); -var ep = new EventProxy(); - -// 在所有指定的事件触发后,将会被调用执行 -// 参数对应各自的事件名的最新数据 -ep.tail('basehead', 'head', 'nav','leftbar', 'foot', 'basefoot', 'main', function(basehead, - head, nav, leftbar, foot, basefoot, mainArr) { - render(basehead, head, nav, leftbar, foot, basefoot, mainArr[0], mainArr[1]); -}); - -// 读取Base头部模板 -fs.readFile('../unitTpl/basehead.html.tpl', 'utf8', function(err, basehead) { - if (err) - throw err; - ep.emit('basehead', basehead); -}); -// 读取头部模板 -fs.readFile('../unitTpl/head.html.tpl', 'utf8', function(err, head) { - if (err) - throw err; - ep.emit('head', head); -}); -// 读取导航模板 -fs.readFile('../unitTpl/nav.html.tpl', 'utf8', function(err, nav) { - if (err) - throw err; - ep.emit('nav', nav); -}); -//读取左侧导航模板 -fs.readFile('../unitTpl/leftbar.html.tpl', 'utf8', function(err, leftbar) { - if (err) - throw err; - ep.emit('leftbar', leftbar); -}); -// 读取尾部模板 -fs.readFile('../unitTpl/foot.html.tpl', 'utf8', function(err, foot) { - if (err) - throw err; - ep.emit('foot', foot); -}); -// 读取尾部模板 -fs.readFile('../unitTpl/basefoot.html.tpl', 'utf8', function(err, basefoot) { - if (err) - throw err; - ep.emit('basefoot', basefoot); -}); -// 读取页面主模板 -fs.readdir("../mainTpl", function(err, dirArr) { - if (err) - throw err; - dirArr.forEach(function(item, index) { - var name = /^(\w+)\.tpl/.exec(item)[1]; - var mainPath = "../mainTpl/" + item; - fs.readFile(mainPath, 'utf8', function(err1, main) { - if (err1) - throw err1; - ep.emit('main', [ main, name ]); - }); - }); -}); - -// 转义html标签 -function decodeHtml(html) { - return String(html).replace(/&/g, "&").replace(/"/g, '"').replace( - /'/g, "'").replace(/</g, "<").replace(/>/g, ">"); -} -// 拼接模板 -function render(basehead, head, nav, leftbar, foot, basefoot, main, name) { - var html = ejs.render(main, { - "page" : { - "basehead" : basehead, - "head" : head, - "nav" : nav, - "leftbar":leftbar, - "foot" : foot, - "basefoot" : basefoot - } - }); - var html = decodeHtml(html); - createFile(html, name); -} -// 生成最终文件 -function createFile(html, name) { - fs.writeFile('../' + name + '.html', html, 'utf8', function(err) { - if (err) - throw err; - console.log(name + '.html is created!'); // 文件被保存 - }); -} diff --git a/disconf-web/html/unitTpl/basefoot.html.tpl b/disconf-web/html/unitTpl/basefoot.html.tpl deleted file mode 100644 index 8a73602be..000000000 --- a/disconf-web/html/unitTpl/basefoot.html.tpl +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/disconf-web/html/unitTpl/basehead.html.tpl b/disconf-web/html/unitTpl/basehead.html.tpl deleted file mode 100644 index 195418039..000000000 --- a/disconf-web/html/unitTpl/basehead.html.tpl +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/disconf-web/html/unitTpl/foot.html.tpl b/disconf-web/html/unitTpl/foot.html.tpl deleted file mode 100644 index 272e506cb..000000000 --- a/disconf-web/html/unitTpl/foot.html.tpl +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - diff --git a/disconf-web/html/unitTpl/head.html.tpl b/disconf-web/html/unitTpl/head.html.tpl deleted file mode 100644 index 3ce326ef8..000000000 --- a/disconf-web/html/unitTpl/head.html.tpl +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/disconf-web/html/unitTpl/leftbar.html.tpl b/disconf-web/html/unitTpl/leftbar.html.tpl deleted file mode 100644 index 04033d47a..000000000 --- a/disconf-web/html/unitTpl/leftbar.html.tpl +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/disconf-web/html/unitTpl/nav.html.tpl b/disconf-web/html/unitTpl/nav.html.tpl deleted file mode 100644 index 30f99007a..000000000 --- a/disconf-web/html/unitTpl/nav.html.tpl +++ /dev/null @@ -1,20 +0,0 @@ -
    -
    -
    - -
    -
    -
    \ No newline at end of file diff --git a/disconf-web/profile/rd/application-demo.properties b/disconf-web/profile/rd/application-demo.properties deleted file mode 100644 index 60a26f20a..000000000 --- a/disconf-web/profile/rd/application-demo.properties +++ /dev/null @@ -1,22 +0,0 @@ - -# -# \u670d\u52a1\u5668\u7684domain -# - -domain=disconf.com - -# -# \u90ae\u7bb1\u8bbe\u7f6e -# - -EMAIL_MONITOR_ON = true -EMAIL_HOST = smtp.163.com -EMAIL_HOST_PASSWORD = password -EMAIL_HOST_USER = sender@163.com -EMAIL_PORT = 25 -DEFAULT_FROM_EMAIL = disconf@163.com - -# -# \u5b9a\u65f6\u6821\u9a8c\u4e2d\u5fc3\u7684\u914d\u7f6e\u4e0e\u6240\u6709\u5ba2\u6237\u7aef\u914d\u7f6e\u7684\u4e00\u81f4\u6027 -# -CHECK_CONSISTENCY_ON= true \ No newline at end of file diff --git a/disconf-web/profile/rd/redis-config.properties b/disconf-web/profile/rd/redis-config.properties index 695ea81c5..3bdbaa59f 100644 --- a/disconf-web/profile/rd/redis-config.properties +++ b/disconf-web/profile/rd/redis-config.properties @@ -1,16 +1,16 @@ redis.group1.retry.times=2 redis.group1.client1.name=BeidouRedis1 -redis.group1.client1.host=127.0.0.1 -redis.group1.client1.port=6379 +redis.group1.client1.host=192.168.30.147 +redis.group1.client1.port=19000 redis.group1.client1.timeout=5000 redis.group1.client1.password=foobared -redis.group1.client2.name=BeidouRedis2 -redis.group1.client2.host=127.0.0.1 -redis.group1.client2.port=6380 -redis.group1.client2.timeout=5000 -redis.group1.client2.password=foobared +#redis.group1.client2.name=BeidouRedis2 +#redis.group1.client2.host=192.168.30.147 +#redis.group1.client2.port=19000 +#redis.group1.client2.timeout=5000 +#redis.group1.client2.password=foobared redis.evictor.delayCheckSeconds=300 redis.evictor.checkPeriodSeconds=30 diff --git a/disconf-web/profile/rd/zoo.properties b/disconf-web/profile/rd/zoo.properties index 4ba077c79..6a65dbaa4 100644 --- a/disconf-web/profile/rd/zoo.properties +++ b/disconf-web/profile/rd/zoo.properties @@ -1,5 +1,4 @@ - -hosts=127.0.0.1:8581,127.0.0.1:8582,127.0.0.1:8583 +hosts=192.168.30.147:2181,192.168.30.148:2181,192.168.30.149:2181 # zookeeper\u7684\u524D\u7F00\u8DEF\u5F84\u540D zookeeper_url_prefix=/disconf \ No newline at end of file diff --git a/disconf-web/sql/201512/20151225.sql b/disconf-web/sql/201512/20151225.sql deleted file mode 100644 index 4f4ca9bd6..000000000 --- a/disconf-web/sql/201512/20151225.sql +++ /dev/null @@ -1,13 +0,0 @@ -USE `disconf`; - -CREATE TABLE `config_history` ( - `id` BIGINT NOT NULL AUTO_INCREMENT, - `config_id` BIGINT NOT NULL, - `old_value` LONGTEXT NOT NULL, - `new_value` LONGTEXT NOT NULL, - `create_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959', - PRIMARY KEY (`id`) -)DEFAULT CHARSET=utf8 ENGINE=InnoDB; - -ALTER TABLE `config` - ADD COLUMN `status` TINYINT(4) NOT NULL DEFAULT '1' COMMENT '状态:1是正常 0是删除' AFTER `type`; diff --git a/disconf-web/sql/20160701/20160701.sql b/disconf-web/sql/20160701/20160701.sql deleted file mode 100644 index e8af637c0..000000000 --- a/disconf-web/sql/20160701/20160701.sql +++ /dev/null @@ -1,10 +0,0 @@ -USE `disconf`; - -ALTER TABLE `config_history` -ADD COLUMN `update_by` BIGINT(20) NULL DEFAULT NULL -AFTER `create_time`; - -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/account/password' , '修改密码' , '0100'), - (2,'/api/account/password' , '修改密码' , '0100'), - (3,'/api/account/password' , '修改密码' , '0000'); diff --git a/disconf-web/sql/deprecated/.gitignore b/disconf-web/sql/deprecated/.gitignore deleted file mode 100644 index c2c4e65e2..000000000 --- a/disconf-web/sql/deprecated/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/20150301 -/20150420 \ No newline at end of file diff --git a/disconf-web/sql/deprecated/1-init_table.sql b/disconf-web/sql/deprecated/1-init_table.sql deleted file mode 100644 index 70500d805..000000000 --- a/disconf-web/sql/deprecated/1-init_table.sql +++ /dev/null @@ -1,56 +0,0 @@ -CREATE DATABASE IF NOT EXISTS `disconf`; -USE `disconf`; - -CREATE TABLE `app` ( - `app_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '唯一的ID(没有啥意义,主键,自增长而已)', - `name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'APP名(一般是产品线+服务名)', - `description` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '介绍', - `create_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '生成时间', - `update_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '修改时', - PRIMARY KEY (`app_id`) -) -COMMENT='app' -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - -CREATE TABLE `config` ( - `config_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '唯一的ID(没有啥意义,主键,自增长而已)', - `type` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '配置文件/配置项', - `name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '配置文件名/配置项KeY名', - `value` TEXT NOT NULL COMMENT '0 配置文件:文件的内容,1 配置项:配置值', - `app_id` BIGINT(20) NOT NULL COMMENT 'appid', - `version` VARCHAR(255) NOT NULL DEFAULT 'DEFAULT_VERSION' COMMENT '版本', - `env_id` BIGINT(20) NOT NULL COMMENT 'envid', - `create_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '生成时间', - `update_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '修改时间', - PRIMARY KEY (`config_id`) -) -COMMENT='配置' -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - -CREATE TABLE `env` ( - `env_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '环境ID(主键,自增长)', - `name` VARCHAR(255) NOT NULL DEFAULT 'DEFAULT_ENV' COMMENT '环境名字', - PRIMARY KEY (`env_id`) -) -COMMENT='rd/qa/local可以自定义,默认为 DEFAULT_ENV' -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - -CREATE TABLE `user` ( - `user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID', - `name` VARCHAR(50) NOT NULL COMMENT '姓名', - `password` VARCHAR(255) NOT NULL COMMENT '密码', - `token` VARCHAR(255) NOT NULL COMMENT 'token', - PRIMARY KEY (`user_id`) -) -COMMENT='用户表' -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - - diff --git a/disconf-web/sql/deprecated/2-data.sql b/disconf-web/sql/deprecated/2-data.sql deleted file mode 100644 index 03a421593..000000000 --- a/disconf-web/sql/deprecated/2-data.sql +++ /dev/null @@ -1,24 +0,0 @@ -USE `disconf`; - -INSERT INTO `env` (`env_id`, `name`) VALUES (1, 'rd'); -INSERT INTO `env` (`env_id`, `name`) VALUES (2, 'qa'); -INSERT INTO `env` (`env_id`, `name`) VALUES (3, 'local'); -INSERT INTO `env` (`env_id`, `name`) VALUES (4, 'online'); - - -INSERT INTO `app` (`app_id`, `name`, `description`, `create_time`, `update_time`) VALUES (2, 'disconf_demo', 'disconf demo', '99991231235959', '99991231235959'); - -INSERT INTO `config` (`config_id`, `type`, `name`, `value`, `app_id`, `version`, `env_id`, `create_time`, `update_time`) -VALUES - (4, 0, 'coefficients.properties', 'coe.baiFaCoe=1.3\ncoe.yuErBaoCoe=1.3\n', 2, '1_0_0_0', 1, '99991231235959', '20141205154137'), - (5, 1, 'moneyInvest', '10000', 2, '1_0_0_0', 1, '99991231235959', '20140902183514'), - (6, 0, 'remote.properties', 'remoteHost=127.0.0.1\r\nremotePort=8081', 2, '1_0_0_0', 1, '20140729174707', '20140804233309'), - (7, 1, 'discountRate', '0.5', 2, '1_0_0_0', 1, '20140801142833', '20140905130141'), - (12, 0, 'redis.properties', 'redis.host=127.0.0.1\nredis.port=6379', 2, '1_0_0_0', 1, '20140811172327', '20141011154244'), - (16, 0, 'static.properties', 'staticVar=147', 2, '1_0_0_0', 1, '20140814202654', '20140905145616'), - (17, 1, 'staticItem', '30', 2, '1_0_0_0', 1, '20140814210709', '20140814211054'), - (29, 0, 'empty.properties', 'redis.host=127.0.0.1\r\nredis.port=8310', 2, '1_0_0_0', 1, '20140909164001', '20140909164125'), - (48, 0, 'myserver.properties', 'server=127.0.0.1:16600,127.0.0.1:16602,127.0.0.1:16603\nretry=5\n', 2, '1_0_0_0', 1, '20140911223117', '20141117153116'), - (119, 0, 'myserver_slave.properties', '#online\r\nserver=127.0.0.1:16700,127.0.0.1:16700,127.0.0.1:16700,127.0.0.1:16700\r\nretry=3', 2, '1_0_0_0', 1, '20141103163302', '20141103163302'), - (122, 0, 'testXml.xml', '\n\n \n \n /tradeMap\n /tradeMap\n \n \n', 2, '1_0_0_0', 1, '20141103202829', '20141110193440'), - (143, 0, 'testXml2.xml', '\n\n \n \n /tradeMap\n /tradeMap\n \n \n', 2, '1_0_0_0', 1, '20141110193605', '20141110193605'); diff --git a/disconf-web/sql/deprecated/20141201/.gitignore b/disconf-web/sql/deprecated/20141201/.gitignore deleted file mode 100644 index a180e975c..000000000 --- a/disconf-web/sql/deprecated/20141201/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/disconf-*.sql diff --git a/disconf-web/sql/deprecated/20141201/disconf.sql b/disconf-web/sql/deprecated/20141201/disconf.sql deleted file mode 100644 index c7119abda..000000000 --- a/disconf-web/sql/deprecated/20141201/disconf.sql +++ /dev/null @@ -1,31 +0,0 @@ -use `disconf`; - -ALTER TABLE `app` - ADD COLUMN `emails` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '邮箱列表逗号分隔' AFTER `update_time`; - -ALTER TABLE `user` - ADD COLUMN `ownapps` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '能操作的APPID,逗号分隔' AFTER `token`; - - -/* testUser1 MhxzKhl9209*/ -/* testUser2 MhxzKhl167*/ -/* testUser3 MhxzKhl783*/ -/* testUser4 MhxzKhl8758*/ -/* testUser5 MhxzKhl112*/ -DELETE FROM `user` where user_id=1; -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (1, 'testUser1', '5eec8499597a115c88e0a9580ae1562ab85d0b1a', 'b9070d385a13357efa09e50e080607c2b299241b','2'); -DELETE FROM `user` where user_id=2; -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (2, 'testUser2', '71e9dc667eefa5a3a4840cb4f1ce22bc246f22f0', 'b169dec42f61ec6cbad88d70e7c4c6b89630ccfb','2'); -DELETE FROM `user` where user_id=3; -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (3, 'testUser3', 'e2cdc4a9195030543e38e19a923f075d54471cc4', 'a1a20b0e03a5191c530cbfc064eda3c16254df64','2'); -DELETE FROM `user` where user_id=4; -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (4, 'testUser4', '5cef2d7e4ada5a615f03e12b569d80aedfb056fc', '007b07fccbc1c82c987f7b8e4651e85cca01cf2b','2'); -DELETE FROM `user` where user_id=5; -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (5, 'testUser5', 'f996eeaa224abe0037d99adbce73c315e13238f9', 'c9dfdcb50a3d84f2b6a4771dcb7c2ceb19e7d281','2'); - - -/* admin admin*/ -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`) VALUES (null, 'admin', 'd033e22ae348aeb5660fc2140aec35850c4da997', 'f28d164d23291c732f64134e6b7d92be3ff8b1b3','2'); - - - diff --git a/disconf-web/sql/deprecated/20141226/.gitignore b/disconf-web/sql/deprecated/20141226/.gitignore deleted file mode 100644 index a180e975c..000000000 --- a/disconf-web/sql/deprecated/20141226/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/disconf-*.sql diff --git a/disconf-web/sql/deprecated/20141226/disconf.sql b/disconf-web/sql/deprecated/20141226/disconf.sql deleted file mode 100644 index a06083b1e..000000000 --- a/disconf-web/sql/deprecated/20141226/disconf.sql +++ /dev/null @@ -1,147 +0,0 @@ -use `disconf`; - -CREATE TABLE `role` ( - `role_id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'id', - `role_name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '角色名', - `create_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '创建时间', - `create_by` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '创建人', - `update_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '更新时间', - `update_by` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '更新人', - PRIMARY KEY (`role_id`) -) -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - -CREATE TABLE `role_resource` ( - `role_res_id` INT(10) NOT NULL AUTO_INCREMENT COMMENT 'role-resource id', - `role_id` INT(10) NOT NULL DEFAULT '0' COMMENT '用户角色id', - `url_pattern` VARCHAR(200) NOT NULL DEFAULT '' COMMENT 'controller_requestMapping_value + method_requestMapping_value', - `url_description` VARCHAR(200) NOT NULL DEFAULT '' COMMENT 'url功能描述', - `method_mask` VARCHAR(4) NOT NULL DEFAULT '' COMMENT 'GET, PUT, POST, DELETE, 1: accessible', - `update_time` VARCHAR(14) NOT NULL DEFAULT '99991231235959' COMMENT '更新时间', - PRIMARY KEY (`role_res_id`) -) -COMMENT='用户角色_url访问权限表' -COLLATE='utf8_general_ci' -ENGINE=InnoDB; - - -INSERT INTO `role` (`role_id`, `role_name`, `create_time`, `create_by`, `update_time`, `update_by`) VALUES (1, '普通人', - '99991231235959', 2, '99991231235959', 2); -INSERT INTO `role` (`role_id`, `role_name`, `create_time`, `create_by`, `update_time`, `update_by`) VALUES (2, '管理员', - '99991231235959', 2, '99991231235959', 2); -INSERT INTO `role` (`role_id`, `role_name`, `create_time`, `create_by`, `update_time`, `update_by`) VALUES (3,'测试管理员', - '99991231235959', 2, '99991231235959', 2); -ALTER TABLE `user` -ADD COLUMN `role_id` BIGINT(20) NOT NULL DEFAULT '1' COMMENT '角色ID' AFTER `ownapps`; - -update `user` set role_id=2,ownapps='' where name='admin'; - -/* admin_read admin_read*/ -INSERT INTO `user` (`user_id`, `name`, `password`, `token`, `ownapps`,`role_id`) VALUES (null, 'admin_read', 'b76f3e20d1c8d0bc17d40158e44097d5eeee8640', '2022ab9c2754d62f9ddba5fded91e4238247ebaf','2', '3'); - - -use disconf; -delete from role_resource; -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/app/list' , 'app列表' , '1000'), - (2,'/api/app/list' , 'app列表' , '1000'), - (3,'/api/app/list' , 'app列表' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/app' , '生成一个app' , '0000'), - (2,'/api/app' , '生成一个app' , '0010'), - (3,'/api/app' , '生成一个app' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/env/list' , 'env-list' , '1000'), - (2,'/api/env/list' , 'env-list' , '1000'), - (3,'/api/env/list' , 'env-list' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/account/session' , '会话' , '1000'), - (2,'/api/account/session' , '会话' , '1000'), - (3,'/api/account/session' , '会话' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/account/signin' , '登录' , '1000'), - (2,'/api/account/signin' , '登录' , '1000'), - (3,'/api/account/signin' , '登录' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/account/signout' , '登出' , '1000'), - (2,'/api/account/signout' , '登出' , '1000'), - (3,'/api/account/signout' , '登出' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/config/item' , '获取配置项' , '1000'), - (2,'/api/config/item' , '获取配置项' , '1000'), - (3,'/api/config/item' , '获取配置项' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/config/file' , '获取配置文件' , '1000'), - (2,'/api/config/file' , '获取配置文件' , '1000'), - (3,'/api/config/file' , '获取配置文件' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/zoo/hosts' , 'zoo' , '1000'), - (2,'/api/zoo/hosts' , 'zoo' , '1000'), - (3,'/api/zoo/hosts' , 'zoo' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/zoo/prefix' , 'zoo' , '1000'), - (2,'/api/zoo/prefix' , 'zoo' , '1000'), - (3,'/api/zoo/prefix' , 'zoo' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/zoo/zkdeploy' , 'zoo' , '1000'), - (2,'/api/zoo/zkdeploy' , 'zoo' , '1000'), - (3,'/api/zoo/zkdeploy' , 'zoo' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/item' , '创建item-config' , '0010'), - (2,'/api/web/config/item' , '创建item-config' , '0010'), - (3,'/api/web/config/item' , '创建item-config' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/file' , '创建file-config' , '0010'), - (2,'/api/web/config/file' , '创建file-config' , '0010'), - (3,'/api/web/config/file' , '创建file-config' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/filetext' , '创建file-config' , '0010'), - (2,'/api/web/config/filetext' , '创建file-config' , '0010'), - (3,'/api/web/config/filetext' , '创建file-config' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/versionlist' , '版本list' , '1000'), - (2,'/api/web/config/versionlist' , '版本list' , '1000'), - (3,'/api/web/config/versionlist' , '版本list' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/list' , 'config-list' , '1000'), - (2,'/api/web/config/list' , 'config-list' , '1000'), - (3,'/api/web/config/list' , 'config-list' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/simple/list' , 'config-list' , '1000'), - (2,'/api/web/config/simple/list' , 'config-list' , '1000'), - (3,'/api/web/config/simple/list' , 'config-list' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/{configId}' , 'get/post' , '1001'), - (2,'/api/web/config/{configId}' , 'get/post' , '1001'), - (3,'/api/web/config/{configId}' , 'get/post' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/zk/{configId}' , 'get-zk' , '1000'), - (2,'/api/web/config/zk/{configId}' , 'get-zk' , '1000'), - (3,'/api/web/config/zk/{configId}' , 'get-zk' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/download/{configId}' , 'download' , '1000'), - (2,'/api/web/config/download/{configId}' , 'download' , '1000'), - (3,'/api/web/config/download/{configId}' , 'download' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/downloadfilebatch' , 'download' , '1000'), - (2,'/api/web/config/downloadfilebatch' , 'download' , '1000'), - (3,'/api/web/config/downloadfilebatch' , 'download' , '1000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/item/{configId}' , 'update' , '0100'), - (2,'/api/web/config/item/{configId}' , 'update' , '0100'), - (3,'/api/web/config/item/{configId}' , 'update' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/file/{configId}' , 'update/post' , '0010'), - (2,'/api/web/config/file/{configId}' , 'update/post' , '0010'), - (3,'/api/web/config/file/{configId}' , 'update/post' , '0000'); -INSERT INTO `role_resource` (`role_id`, `url_pattern`, `url_description`, `method_mask`) VALUES - (1,'/api/web/config/filetext/{configId}' , 'update' , '0100'), - (2,'/api/web/config/filetext/{configId}' , 'update' , '0100'), - (3,'/api/web/config/filetext/{configId}' , 'update' , '0000'); - - -INSERT INTO `config` (`config_id`, `type`, `name`, `value`, `app_id`, `version`, `env_id`, `create_time`, `update_time`) -VALUES - (146, 0, 'code.properties', 'syserror.paramtype=\\u8bf7\\u6c42\\u53c2\\u6570\\u89e3\\u6790\\u9519\" + \"\\u8bef', 2, '1_0_0_0', 1, '20150107115835', '20150107115835'); diff --git a/disconf-web/sql/deprecated/20150101/disconf.sql b/disconf-web/sql/deprecated/20150101/disconf.sql deleted file mode 100644 index a02d8a0fd..000000000 --- a/disconf-web/sql/deprecated/20150101/disconf.sql +++ /dev/null @@ -1,5 +0,0 @@ -use `disconf`; - -INSERT INTO `config` (`config_id`, `type`, `name`, `value`, `app_id`, `version`, `env_id`, `create_time`, `update_time`) -VALUES - (147, 0, 'testJson.json', '{\"message\": {}, \"success\": \"true\"}', 2, '1_0_0_0', 1, '20150121150626', '20150121153650'); diff --git a/disconf-web/sql/deprecated/20150320/disconf.sql b/disconf-web/sql/deprecated/20150320/disconf.sql deleted file mode 100644 index 278b3133a..000000000 --- a/disconf-web/sql/deprecated/20150320/disconf.sql +++ /dev/null @@ -1,6 +0,0 @@ -use `disconf`; - -INSERT INTO `config` (`config_id`, `type`, `name`, `value`, `app_id`, `version`, `env_id`, `create_time`, `update_time`) -VALUES - (148, 0, 'autoconfig.properties', 'auto=bbdxxjdccd', 2, '1_0_0_0', 1, '20150320130619', '20150320224956'), - (149, 0, 'autoconfig2.properties', 'auto2=cd', 2, '1_0_0_0', 1, '20150320130625', '20150320203808'); diff --git a/disconf-web/sql/deprecated/20150611/.gitignore b/disconf-web/sql/deprecated/20150611/.gitignore deleted file mode 100644 index 48e029b16..000000000 --- a/disconf-web/sql/deprecated/20150611/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.sql \ No newline at end of file diff --git a/disconf-web/sql/deprecated/readme.txt b/disconf-web/sql/deprecated/readme.txt deleted file mode 100644 index 21dc62dbb..000000000 --- a/disconf-web/sql/deprecated/readme.txt +++ /dev/null @@ -1,12 +0,0 @@ -目录已经废弃 - -此目录有所有SQL改动记录 - -请先后执行: - -1-init_table.sql 主要是生成tables -2-data.sql 主要是生成测试数据 -20141201/disconf.sql 升级,支持 管理员角色、用户邮箱 -20141226/disconf.sql 升级,支持 URL权限控制 -20150101/disconf.sql 增加一个测试数据 -20150320/disconf.sql 增加reloadable config的测试文件 \ No newline at end of file diff --git a/disconf-web/src/main/resources/myconfig/applicationContext-cache.xml b/disconf-web/src/main/resources/myconfig/applicationContext-cache.xml index 899e1973e..fe32ee379 100644 --- a/disconf-web/src/main/resources/myconfig/applicationContext-cache.xml +++ b/disconf-web/src/main/resources/myconfig/applicationContext-cache.xml @@ -9,7 +9,6 @@ - @@ -50,28 +49,28 @@ - - - ${redis.group1.client2.name} - - - ${redis.group1.client2.host} - - - ${redis.group1.client2.port} - - - ${redis.group1.client2.timeout} - - - ${redis.group1.client2.password} - - + + + + + + + + + + + + + + + + + - - - - - + + + + + \ No newline at end of file diff --git a/docs/image/DisconfMgrBean.png b/docs/image/DisconfMgrBean.png new file mode 100644 index 0000000000000000000000000000000000000000..dfe10cd0e1db4534d79e40b7b362d5d51a76b2f2 GIT binary patch literal 205780 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%0AaKksjS>w5VQ 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

    KqTBeR%ncs(P-@pV*L`%~b5p&Eh>pn<$W! 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 00c6c60fd..21327c48e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ disconf-client disconf-core + disconf-web 2015 @@ -38,7 +39,7 @@ 1.6 1.6 1.6 - 4.1.7.RELEASE + 3.2.9.RELEASE 1.4.5.RELEASE 4.10 2.0 @@ -157,7 +158,7 @@ org.apache.zookeeper zookeeper - 3.3.6 + 3.4.10 com.sun.jmx @@ -400,12 +401,6 @@ - - org.springframework - spring-test - ${spring.version} - - com.h2database h2 @@ -457,7 +452,7 @@ org.hibernate hibernate-validator - 5.0.1.Final + 4.3.2.Final @@ -694,6 +689,9 @@ jar + + UTF-8 + @@ -731,7 +729,7 @@ release - + + + + xbniao-thirdparty + xbniao-thirdparty + http://192.168.30.112:8081/nexus/content/repositories/thirdparty/ + + + xbniao-snapshots + Nexus Snapshot Repository + http://192.168.30.112:8081/nexus/content/repositories/snapshots/ + @@ -771,7 +781,7 @@ - + + + \ No newline at end of file diff --git a/sql/.gitignore b/sql/.gitignore deleted file mode 100644 index 617c280c2..000000000 --- a/sql/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -didi/2016-06-21-2.sql -didi \ No newline at end of file From d77022bfa14076e6b82e79639f6826b01921e1c4 Mon Sep 17 00:00:00 2001 From: songfei Date: Fri, 11 Aug 2017 14:47:40 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=96=87=E6=9C=AC=E6=9B=B4=E6=96=B0=EF=BC=8C?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E4=B9=B1=E7=A0=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../addons/properties/ReloadablePropertiesFactoryBean.java | 1 + .../core/filetype/impl/DisconfAnyFileProcessorImpl.java | 2 ++ .../core/processor/impl/DisconfFileCoreProcessorImpl.java | 2 +- .../disconf/core/common/restful/impl/RestfulMgrImpl.java | 3 +-- .../web/web/config/controller/ConfigUpdateController.java | 6 +++--- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java b/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java index 349485762..35ec45ae2 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/addons/properties/ReloadablePropertiesFactoryBean.java @@ -125,6 +125,7 @@ private String getFileRelativePath(String fileName){ if (fileName != null) { int index = fileName.indexOf(':'); if (index < 0) { + return fileName; } else { fileName = fileName.substring(index + 1); } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/core/filetype/impl/DisconfAnyFileProcessorImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/core/filetype/impl/DisconfAnyFileProcessorImpl.java index 61e11f632..2634ec520 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/core/filetype/impl/DisconfAnyFileProcessorImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/core/filetype/impl/DisconfAnyFileProcessorImpl.java @@ -14,6 +14,8 @@ public class DisconfAnyFileProcessorImpl implements DisconfFileTypeProcessor { @Override public Map getKvMap(String fileName) throws Exception { // TODO Auto-generated method stub + + return null; } diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/core/processor/impl/DisconfFileCoreProcessorImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/core/processor/impl/DisconfFileCoreProcessorImpl.java index fc3aee247..d2ce6989f 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/core/processor/impl/DisconfFileCoreProcessorImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/core/processor/impl/DisconfFileCoreProcessorImpl.java @@ -129,7 +129,7 @@ private void updateOneConfFile(String fileName, DisconfCenterFile disconfCenterF } // - // 注入到仓库中 + // 注入到仓库中,Reload非注解形式bean属性值 // disconfStoreProcessor.inject2Store(fileName, new DisconfValue(null, dataMap)); LOGGER.debug("inject ok."); diff --git a/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java b/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java index 00212dd3a..0546c7fe5 100644 --- a/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java +++ b/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java @@ -113,8 +113,7 @@ public String downloadFromServer(RemoteUrl remoteUrl, String fileName, String lo if (targetDirPath != null) { // - if (enableLocalDownloadDirInClassPath || !targetDirPath.equals(ClassLoaderUtil.getClassPath - ())) { + if (enableLocalDownloadDirInClassPath || !targetDirPath.equals(ClassLoaderUtil.getClassPath())) { localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, targetDirPath, fileName, true); } } diff --git a/disconf-web/src/main/java/com/baidu/disconf/web/web/config/controller/ConfigUpdateController.java b/disconf-web/src/main/java/com/baidu/disconf/web/web/config/controller/ConfigUpdateController.java index 188e85fff..471510dc6 100644 --- a/disconf-web/src/main/java/com/baidu/disconf/web/web/config/controller/ConfigUpdateController.java +++ b/disconf-web/src/main/java/com/baidu/disconf/web/web/config/controller/ConfigUpdateController.java @@ -136,16 +136,16 @@ public JsonObjectBase updateFileWithText(@PathVariable long configId, @NotNull S // // 更新 // - String emailNotification = ""; + String emailNotification; try { - String str = new String(fileContent.getBytes(), "UTF-8"); + String str = new String(fileContent.getBytes("UTF-8"), "UTF-8"); LOG.info("receive file: " + str); emailNotification = configMgr.updateItemValue(configId, str); LOG.info("update " + configId + " ok"); - } catch (Exception e) { + }catch (Exception e) { throw new FileUploadException("upload.file.error", e); } From 1d0c8b039952cebe655c101c5511a0e882d47811 Mon Sep 17 00:00:00 2001 From: songfei Date: Wed, 16 Aug 2017 10:57:01 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=A2=B3=E7=90=86=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E6=94=B9CLASSPATH=EF=BC=8CUSER=5FDEFINED=5FDIR?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E4=B8=8B=E8=BD=BD=E6=94=AF=E6=8C=81=EF=BC=88?= =?UTF-8?q?=201.disconf.user=5Fdefine=5Fdownload=5Fdir=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E4=B8=8D=E4=B8=BA=E7=A9=BA=E6=97=B6=EF=BC=8C=E6=89=8DCOPY?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E8=87=B3=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E7=9B=AE=E5=BD=95,=E4=B8=8D?= =?UTF-8?q?=E5=9C=A8=E4=BD=BF=E7=94=A8=E9=BB=98=E8=AE=A4=E5=9D=87=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=9A=84=E9=80=BB=E8=BE=91=202.disconf.enable=5Flocal?= =?UTF-8?q?=5Fdownload=5Fdir=5Fin=5Fclass=5Fpath=EF=BC=8C=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=AF=86=E5=88=AB=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E5=B9=B6=E4=B8=8B=E8=BD=BD=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=88=B0=E7=9B=B8=E5=BA=94Classpath=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/fetcher/impl/FetcherMgrImpl.java | 5 ++-- disconf-core/pom.xml | 2 +- .../common/restful/impl/RestfulMgrImpl.java | 23 +++++++++---------- .../profile/rd/redis-config.properties | 6 ++--- disconf-web/profile/rd/zoo.properties | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/disconf-client/src/main/java/com/baidu/disconf/client/fetcher/impl/FetcherMgrImpl.java b/disconf-client/src/main/java/com/baidu/disconf/client/fetcher/impl/FetcherMgrImpl.java index 806750382..541bb6f23 100644 --- a/disconf-client/src/main/java/com/baidu/disconf/client/fetcher/impl/FetcherMgrImpl.java +++ b/disconf-client/src/main/java/com/baidu/disconf/client/fetcher/impl/FetcherMgrImpl.java @@ -49,9 +49,8 @@ public class FetcherMgrImpl implements FetcherMgr { // 创建对象 // public FetcherMgrImpl(RestfulMgr restfulMgr, int retryTime, int retrySleepSeconds, - boolean enableLocalDownloadDirInClassPath, String localDownloadDir, String - localDownloadDirTemp, List - hostList) { + boolean enableLocalDownloadDirInClassPath, String localDownloadDir, + String localDownloadDirTemp, List hostList) { this.restfulMgr = restfulMgr; diff --git a/disconf-core/pom.xml b/disconf-core/pom.xml index 39145c935..7355210c0 100644 --- a/disconf-core/pom.xml +++ b/disconf-core/pom.xml @@ -43,7 +43,7 @@ org.apache.httpcomponents httpclient - 4.5.1 + 4.5.3 diff --git a/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java b/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java index 0546c7fe5..d9f16fb87 100644 --- a/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java +++ b/disconf-core/src/main/java/com/baidu/disconf/core/common/restful/impl/RestfulMgrImpl.java @@ -1,5 +1,7 @@ package com.baidu.disconf.core.common.restful.impl; +import com.google.common.base.Strings; + import java.io.File; import java.net.URL; @@ -12,7 +14,6 @@ import com.baidu.disconf.core.common.restful.retry.RetryStrategy; import com.baidu.disconf.core.common.restful.type.FetchConfFile; import com.baidu.disconf.core.common.restful.type.RestfulGet; -import com.baidu.disconf.core.common.utils.ClassLoaderUtil; import com.baidu.disconf.core.common.utils.MyStringUtils; import com.baidu.disconf.core.common.utils.OsUtil; import com.baidu.disconf.core.common.utils.http.HttpClientUtil; @@ -103,19 +104,16 @@ public String downloadFromServer(RemoteUrl remoteUrl, String fileName, String lo try { // 可重试的下载 - File tmpFilePathUniqueFile = retryDownload(localFileDirTemp, fileName, remoteUrl, retryTimes, - retrySleepSeconds); - - // 将 tmp file copy localFileDir - localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, localFileDir, fileName, false); + File tmpFilePathUniqueFile = retryDownload(localFileDirTemp, fileName, remoteUrl, retryTimes, retrySleepSeconds); - // mv 到指定目录 - if (targetDirPath != null) { + // 拷贝配置文件至用户自定义路径 + if (!Strings.isNullOrEmpty(localFileDir) && new File(localFileDir).exists()) { + localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, localFileDir, fileName, false); + } - // - if (enableLocalDownloadDirInClassPath || !targetDirPath.equals(ClassLoaderUtil.getClassPath())) { - localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, targetDirPath, fileName, true); - } + // 移动配置文件到应用CLASSPATH路径下 + if (targetDirPath != null && enableLocalDownloadDirInClassPath) { + localFile = transfer2SpecifyDir(tmpFilePathUniqueFile, targetDirPath, fileName, true); } LOGGER.debug("Move to: " + localFile.getAbsolutePath()); @@ -168,6 +166,7 @@ private File retryDownload(String localFileDirTemp, String fileName, RemoteUrl r retrySleepSeconds) throws Exception { + //default disconf temp file path if (localFileDirTemp == null) { localFileDirTemp = "./disconf/download"; } diff --git a/disconf-web/profile/rd/redis-config.properties b/disconf-web/profile/rd/redis-config.properties index 3bdbaa59f..56bfa870b 100644 --- a/disconf-web/profile/rd/redis-config.properties +++ b/disconf-web/profile/rd/redis-config.properties @@ -1,10 +1,10 @@ redis.group1.retry.times=2 redis.group1.client1.name=BeidouRedis1 -redis.group1.client1.host=192.168.30.147 -redis.group1.client1.port=19000 +redis.group1.client1.host=127.0.0.1 +redis.group1.client1.port=6379 redis.group1.client1.timeout=5000 -redis.group1.client1.password=foobared +redis.group1.client1.password= #redis.group1.client2.name=BeidouRedis2 #redis.group1.client2.host=192.168.30.147 diff --git a/disconf-web/profile/rd/zoo.properties b/disconf-web/profile/rd/zoo.properties index 6a65dbaa4..b4f4fede1 100644 --- a/disconf-web/profile/rd/zoo.properties +++ b/disconf-web/profile/rd/zoo.properties @@ -1,4 +1,4 @@ -hosts=192.168.30.147:2181,192.168.30.148:2181,192.168.30.149:2181 +hosts=127.0.0.1:2181 # zookeeper\u7684\u524D\u7F00\u8DEF\u5F84\u540D zookeeper_url_prefix=/disconf \ No newline at end of file From b8e1b93f81388a31e23fce6ca56e6ee0eb212d63 Mon Sep 17 00:00:00 2001 From: songfei Date: Wed, 16 Aug 2017 16:59:54 +0800 Subject: [PATCH 6/6] =?UTF-8?q?1.=20=E4=BF=AE=E6=94=B9=E4=B8=BB=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=B8=BA2.3.41=EF=BC=88=E9=81=BF=E5=85=8D=E5=90=8E?= =?UTF-8?q?=E7=BB=AD=E5=86=85=E9=83=A8=E4=BD=BF=E7=94=A8=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E4=BB=8Emaven=E4=B8=AD=E5=A4=AE=E4=BB=93=E5=BA=93=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=8E=9F=E7=89=88=E4=BE=9D=E8=B5=96=EF=BC=89=202.=20?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8slf4j+log4j=E6=97=A5?= =?UTF-8?q?=E5=BF=97=EF=BC=8C=E7=A7=BB=E9=99=A4=E5=8E=9F=E6=9C=89Logback?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=203.=20=E4=BF=AE=E6=94=B9=E9=9B=86=E6=88=90?= =?UTF-8?q?=E6=97=B6=E5=AE=B9=E6=98=93=E5=86=B2=E7=AA=81=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E5=8C=85=E7=9A=84scope=E5=B1=9E=E6=80=A7=E4=B8=BAprovided=205.?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E9=82=AE=E4=BB=B6=E5=9C=A8=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E6=A8=A1=E5=BC=8F=E4=B8=8B=E6=97=A0=E6=B3=95=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E5=8F=91=E9=80=81=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- disconf-client/deploy/package-jar.xml | 1 - disconf-client/pom.xml | 32 +++++--- .../src/test/resources/log4j.properties | 19 +++++ disconf-client/src/test/resources/logback.xml | 50 ------------ disconf-core/pom.xml | 10 ++- disconf-web/pom.xml | 13 +-- disconf-web/profile/rd/logback.xml | 74 ----------------- .../web/config/ApplicationPropertyConfig.java | 38 +++++++-- .../config/service/impl/ConfigMgrImpl.java | 13 ++- .../baidu/disconf/web/utils/DiffUtils.java | 3 +- .../dsp/common/utils/email/MailBean.java | 40 ++-------- .../src/main/resources/applicationContext.xml | 23 ++++++ .../disconf/web/test/common/BaseTestCase.java | 2 +- .../service/config/dao/SpringMailTest.java | 79 +++++++++++++++++++ .../resources/applicationContext-mail.xml | 32 ++++++++ .../src/test/resources/log4j.properties | 19 +++++ pom.xml | 55 +++++-------- 17 files changed, 276 insertions(+), 227 deletions(-) create mode 100644 disconf-client/src/test/resources/log4j.properties delete mode 100644 disconf-client/src/test/resources/logback.xml delete mode 100644 disconf-web/profile/rd/logback.xml create mode 100644 disconf-web/src/test/java/com/baidu/disconf/web/test/service/config/dao/SpringMailTest.java create mode 100644 disconf-web/src/test/resources/applicationContext-mail.xml create mode 100644 disconf-web/src/test/resources/log4j.properties diff --git a/disconf-client/deploy/package-jar.xml b/disconf-client/deploy/package-jar.xml index 0008bcd66..4ba99c24b 100644 --- a/disconf-client/deploy/package-jar.xml +++ b/disconf-client/deploy/package-jar.xml @@ -16,7 +16,6 @@ target/classes disconf.properties - logback.xml / diff --git a/disconf-client/pom.xml b/disconf-client/pom.xml index 524931042..d9499c736 100644 --- a/disconf-client/pom.xml +++ b/disconf-client/pom.xml @@ -10,7 +10,7 @@ com.baidu.disconf disconf-base - 2.6.36 + 2.6.41 @@ -67,6 +67,7 @@ com.google.code.gson gson + provided @@ -83,6 +84,7 @@ com.google.guava guava + provided @@ -93,21 +95,29 @@ - ch.qos.logback - logback-core - provided - - - - ch.qos.logback - logback-classic + org.slf4j + slf4j-api provided - org.slf4j - slf4j-api + log4j + log4j provided + + + com.sun.jmx + jmxri + + + com.sun.jdmk + jmxtools + + + javax.jms + jms + + diff --git a/disconf-client/src/test/resources/log4j.properties b/disconf-client/src/test/resources/log4j.properties new file mode 100644 index 000000000..8b694342d --- /dev/null +++ b/disconf-client/src/test/resources/log4j.properties @@ -0,0 +1,19 @@ + +log4j.rootLogger=INFO,dailyRolling,CONSOLE + +log4j.logger.org.apache.zookeeper=WARN +log4j.logger.org.springframework=INFO +log4j.logger.org.springframework.aop.framework.Cglib2AopProxy = INFO + +log4j.appender.dailyRolling=org.apache.log4j.DailyRollingFileAppender +log4j.appender.dailyRolling.File=../log/disconf-client.log +log4j.appender.dailyRolling.layout=org.apache.log4j.PatternLayout +log4j.appender.dailyRolling.layout.ConversionPattern=%d [%t] %-5p %-17c{2} (%13F:%L) %3x - %m%n + +log4j.appender.Threshold=WARN +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Target=System.out +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %-17c{2} (%13F:%L) %3x - %m%n + + diff --git a/disconf-client/src/test/resources/logback.xml b/disconf-client/src/test/resources/logback.xml deleted file mode 100644 index d5b013f21..000000000 --- a/disconf-client/src/test/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - %date [%thread] %-5level %logger{80} - %msg%n - - - - - ${log.base}.log - - ${log.base}.%d{yyyy-MM-dd}.log - - - %date [%thread] %-5level %logger{80} - %msg%n - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/disconf-core/pom.xml b/disconf-core/pom.xml index 7355210c0..cc52dc027 100644 --- a/disconf-core/pom.xml +++ b/disconf-core/pom.xml @@ -13,7 +13,7 @@ com.baidu.disconf disconf-base - 2.6.36 + 2.6.41 @@ -32,7 +32,8 @@ com.google.guava guava - 19.0-rc2 + 19.0 + provided @@ -44,11 +45,13 @@ org.apache.httpcomponents httpclient 4.5.3 + provided com.google.code.gson gson + provided @@ -84,6 +87,7 @@ org.slf4j slf4j-api + provided @@ -193,7 +197,6 @@ *.conf **/*.*.conf - logback.xml @@ -203,7 +206,6 @@ *.conf **/*.*.conf *.properties - logback.xml diff --git a/disconf-web/pom.xml b/disconf-web/pom.xml index a87b7431f..0cdd56938 100644 --- a/disconf-web/pom.xml +++ b/disconf-web/pom.xml @@ -12,7 +12,7 @@ com.baidu.disconf disconf-base - 2.6.36 + 2.6.41 @@ -304,23 +304,12 @@ - - ch.qos.logback - logback-core - - - - ch.qos.logback - logback-classic - - org.slf4j slf4j-api - org.springframework spring-test diff --git a/disconf-web/profile/rd/logback.xml b/disconf-web/profile/rd/logback.xml deleted file mode 100644 index a38057de6..000000000 --- a/disconf-web/profile/rd/logback.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - UTF-8 - - %X{sessionId} %date [%thread] %-5level %logger{80} - %msg%n - - - - - ${log.base}.log - UTF-8 - - ${log.base}.log.%d{yyyy-MM-dd} - - - %X{sessionId} %date [%thread] %-5level %logger{80} - %msg%n - - - - - UTF-8 - ${log.monitor}.log - - ${log.base}.log.%d{yyyy-MM-dd} - - - %X{sessionId} %date [%thread] %-5level %logger{80} - %msg%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/disconf-web/src/main/java/com/baidu/disconf/web/config/ApplicationPropertyConfig.java b/disconf-web/src/main/java/com/baidu/disconf/web/config/ApplicationPropertyConfig.java index 863a32564..b6ce19f8a 100644 --- a/disconf-web/src/main/java/com/baidu/disconf/web/config/ApplicationPropertyConfig.java +++ b/disconf-web/src/main/java/com/baidu/disconf/web/config/ApplicationPropertyConfig.java @@ -24,6 +24,10 @@ public class ApplicationPropertyConfig { private String emailReceiver; + private String emailProtocol; + private String emailEncoding; + + private boolean emailMonitorOn = false; // @@ -109,12 +113,36 @@ public void setDomain(String domain) { this.domain = domain; } + public String getEmailProtocol() { + return emailProtocol; + } + + public void setEmailProtocol(String emailProtocol) { + this.emailProtocol = emailProtocol; + } + + public String getEmailEncoding() { + return emailEncoding; + } + + public void setEmailEncoding(String emailEncoding) { + this.emailEncoding = emailEncoding; + } + @Override public String toString() { - return "ApplicationPropertyConfig [emailHost=" + emailHost + ", emailPassword=" + emailPassword + - ", emailUser=" + emailUser + ", emailPort=" + emailPort + ", fromEmail=" + fromEmail + - ", emailReceiver=" + emailReceiver + ", emailMonitorOn=" + emailMonitorOn + ", checkConsistencyOn=" + - checkConsistencyOn + "]"; + return "ApplicationPropertyConfig{" + + "emailHost='" + emailHost + '\'' + + ", emailPassword='" + emailPassword + '\'' + + ", emailUser='" + emailUser + '\'' + + ", emailPort='" + emailPort + '\'' + + ", fromEmail='" + fromEmail + '\'' + + ", emailReceiver='" + emailReceiver + '\'' + + ", emailProtocol='" + emailProtocol + '\'' + + ", emailEncoding='" + emailEncoding + '\'' + + ", emailMonitorOn=" + emailMonitorOn + + ", checkConsistencyOn=" + checkConsistencyOn + + ", domain='" + domain + '\'' + + '}'; } - } diff --git a/disconf-web/src/main/java/com/baidu/disconf/web/service/config/service/impl/ConfigMgrImpl.java b/disconf-web/src/main/java/com/baidu/disconf/web/service/config/service/impl/ConfigMgrImpl.java index ba3b04b3f..cfdfec730 100644 --- a/disconf-web/src/main/java/com/baidu/disconf/web/service/config/service/impl/ConfigMgrImpl.java +++ b/disconf-web/src/main/java/com/baidu/disconf/web/service/config/service/impl/ConfigMgrImpl.java @@ -22,6 +22,7 @@ import com.baidu.disconf.web.config.ApplicationPropertyConfig; import com.baidu.disconf.web.innerapi.zookeeper.ZooKeeperDriver; import com.baidu.disconf.web.service.app.bo.App; +import com.baidu.disconf.web.service.app.dao.AppDao; import com.baidu.disconf.web.service.app.service.AppMgr; import com.baidu.disconf.web.service.config.bo.Config; import com.baidu.disconf.web.service.config.dao.ConfigDao; @@ -32,6 +33,7 @@ import com.baidu.disconf.web.service.config.vo.ConfListVo; import com.baidu.disconf.web.service.config.vo.MachineListVo; import com.baidu.disconf.web.service.env.bo.Env; +import com.baidu.disconf.web.service.env.dao.EnvDao; import com.baidu.disconf.web.service.env.service.EnvMgr; import com.baidu.disconf.web.service.zookeeper.dto.ZkDisconfData; import com.baidu.disconf.web.service.zookeeper.dto.ZkDisconfData.ZkDisconfDataItem; @@ -60,6 +62,12 @@ public class ConfigMgrImpl implements ConfigMgr { @Autowired private ConfigDao configDao; + @Autowired + private AppDao appDao; + + @Autowired + private EnvDao envDao; + @Autowired private AppMgr appMgr; @@ -263,6 +271,9 @@ public String updateItemValue(Long configId, String value) { Config config = getConfigById(configId); String oldValue = config.getValue(); + App app = appDao.get(config.getAppId()); + Env env = envDao.get(config.getEnvId()); + // // 配置数据库的值 encode to db // @@ -276,7 +287,7 @@ public String updateItemValue(Long configId, String value) { if (applicationPropertyConfig.isEmailMonitorOn()) { boolean isSendSuccess = logMailBean.sendHtmlEmail(toEmails, - " config update", DiffUtils.getDiff(CodeUtils.unicodeToUtf8(oldValue), + " [" +File.separator + app.getName() + File.separator + env.getName() + File.separator + config.getVersion() + File.separator + config.getName() + "] update !", DiffUtils.getDiff(CodeUtils.unicodeToUtf8(oldValue), value, config.toString(), getConfigUrlHtml(config))); diff --git a/disconf-web/src/main/java/com/baidu/disconf/web/utils/DiffUtils.java b/disconf-web/src/main/java/com/baidu/disconf/web/utils/DiffUtils.java index 28d9221e0..a0d922262 100644 --- a/disconf-web/src/main/java/com/baidu/disconf/web/utils/DiffUtils.java +++ b/disconf-web/src/main/java/com/baidu/disconf/web/utils/DiffUtils.java @@ -88,7 +88,8 @@ public static String getDiff(String old, String newData, String identify, String } } - return contentString + diff + oldValue + newValue; +// return contentString + diff + oldValue + newValue; + return diff + oldValue + newValue + htmlClick; } } catch (IOException e) { diff --git a/disconf-web/src/main/java/com/baidu/dsp/common/utils/email/MailBean.java b/disconf-web/src/main/java/com/baidu/dsp/common/utils/email/MailBean.java index 8dfa05f35..f5068b05a 100644 --- a/disconf-web/src/main/java/com/baidu/dsp/common/utils/email/MailBean.java +++ b/disconf-web/src/main/java/com/baidu/dsp/common/utils/email/MailBean.java @@ -10,12 +10,15 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import com.baidu.disconf.web.config.ApplicationPropertyConfig; +import java.util.Properties; + /** * 邮件发送公共类 * @@ -23,15 +26,15 @@ * @version 1.0.0 */ @Service -public class MailBean implements InitializingBean { +public class MailBean { protected static final Logger LOG = LoggerFactory.getLogger(MailBean.class); @Autowired private ApplicationPropertyConfig emailProperties; - // mail sender - private JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + @Autowired + private JavaMailSender mailSender; /** * 发送html邮件 @@ -39,13 +42,12 @@ public class MailBean implements InitializingBean { * @throws MessagingException * @throws AddressException */ - public void sendHtmlMail(String from, String[] to, String title, String text) - throws AddressException, MessagingException { + public void sendHtmlMail(String from, String[] to, String title, String text) throws AddressException, MessagingException { long start = System.currentTimeMillis(); MimeMessage mimeMessage = mailSender.createMimeMessage(); - MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "GBK"); + MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, emailProperties.getEmailEncoding()); InternetAddress[] toArray = new InternetAddress[to.length]; for (int i = 0; i < to.length; i++) { @@ -62,30 +64,4 @@ public void sendHtmlMail(String from, String[] to, String title, String text) LOG.info("send mail start:" + start + " end :" + end); } - /** - * 设置邮箱host,用户名和密码 - */ - @Override - public void afterPropertiesSet() throws Exception { - mailSender.setHost(emailProperties.getEmailHost()); - - if (!StringUtils.isEmpty(emailProperties.getEmailUser())) { - mailSender.setUsername(emailProperties.getEmailUser()); - } - - if (!StringUtils.isEmpty(emailProperties.getEmailPassword())) { - mailSender.setPassword(emailProperties.getEmailPassword()); - } - - if (!StringUtils.isEmpty(emailProperties.getEmailPort())) { - - try { - - Integer port = Integer.parseInt(emailProperties.getEmailPort()); - mailSender.setPort(port); - } catch (Exception e) { - LOG.error(e.toString()); - } - } - } } diff --git a/disconf-web/src/main/resources/applicationContext.xml b/disconf-web/src/main/resources/applicationContext.xml index 623c7e857..c56587fe8 100644 --- a/disconf-web/src/main/resources/applicationContext.xml +++ b/disconf-web/src/main/resources/applicationContext.xml @@ -65,6 +65,29 @@ + + + + + + + + + + + + + + true + true + true + true + + + diff --git a/disconf-web/src/test/java/com/baidu/disconf/web/test/common/BaseTestCase.java b/disconf-web/src/test/java/com/baidu/disconf/web/test/common/BaseTestCase.java index d2922ca52..76ee68847 100644 --- a/disconf-web/src/test/java/com/baidu/disconf/web/test/common/BaseTestCase.java +++ b/disconf-web/src/test/java/com/baidu/disconf/web/test/common/BaseTestCase.java @@ -12,7 +12,7 @@ * @version 2013-12-13 */ @TestExecutionListeners(BaseTestBeforeClass.class) -@ContextConfiguration(locations = "classpath:applicationContext.xml") +@ContextConfiguration(locations = {"classpath:applicationContext-mail.xml","classpath:applicationContext-dbconfig-test.xml"}) @TransactionConfiguration(transactionManager = "onedbTransactionManagerTest") @ActiveProfiles({ "db-test" }) public class BaseTestCase extends AbstractTestCase { diff --git a/disconf-web/src/test/java/com/baidu/disconf/web/test/service/config/dao/SpringMailTest.java b/disconf-web/src/test/java/com/baidu/disconf/web/test/service/config/dao/SpringMailTest.java new file mode 100644 index 000000000..973d7b3c6 --- /dev/null +++ b/disconf-web/src/test/java/com/baidu/disconf/web/test/service/config/dao/SpringMailTest.java @@ -0,0 +1,79 @@ +package com.baidu.disconf.web.test.service.config.dao; + + +import com.baidu.disconf.web.test.common.BaseTestCase; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; + +import java.io.File; + +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeUtility; + +public class SpringMailTest extends BaseTestCase { + @Autowired + private JavaMailSender javaMailSender; + + @Test + public void testSimpleTextMail(){ //发送普通文本邮件 + SimpleMailMessage mailMessage = new SimpleMailMessage(); + mailMessage.setFrom("songfei@xbniao.com");// 发送者,可选的 + mailMessage.setTo("lysongfei@126.com");//接受者 + mailMessage.setSubject("测试邮件");//主题 + mailMessage.setText("Test Email send by javaMailSender!");//邮件内容 + + javaMailSender.send(mailMessage); + } + + @Test + public void testMimeMail() throws Exception { //发送HTML格式的邮件 + + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom("songfei@xbniao.com"); + helper.setTo("lysongfei@126.com"); + helper.setSubject("主题:嵌入静态资源"); + helper.setText("", true); + + javaMailSender.send(mimeMessage); + } + + @Test + public void testMimeInlineMail() throws Exception { //发送HTML格式含图片的邮件 + + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom("songfei@xbniao.com"); + helper.setTo("lysongfei@126.com"); + helper.setSubject("主题:嵌入静态资源"); + helper.setText("", true); + FileSystemResource logoFile = new FileSystemResource(new File("/Users/Song/Downloads/401500600021_.jpg")); + helper.addInline("logo", logoFile); + + javaMailSender.send(mimeMessage); + } + + @Test + public void testAttachmentMail() throws Exception { //发送含附件的邮件 + + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);// 第二个参数设置为true,表示允许添加附件 + helper.setFrom("songfei@xbniao.com"); + helper.setTo("lysongfei@126.com"); + helper.setSubject("发送含图片附件的邮件"); + helper.setText("含有附件的邮件"); + + helper.addAttachment(MimeUtility.encodeText("附件-1.jpg"), new File("/Users/Song/Downloads/391500600020_.jpg")); + helper.addAttachment(MimeUtility.encodeText("附件-2.jpg"), new File("/Users/Song/Downloads/381500600019_.jpg")); + + javaMailSender.send(mimeMessage); + } + + +} diff --git a/disconf-web/src/test/resources/applicationContext-mail.xml b/disconf-web/src/test/resources/applicationContext-mail.xml new file mode 100644 index 000000000..bce725fa8 --- /dev/null +++ b/disconf-web/src/test/resources/applicationContext-mail.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + true + true + true + true + + + + + + \ No newline at end of file diff --git a/disconf-web/src/test/resources/log4j.properties b/disconf-web/src/test/resources/log4j.properties new file mode 100644 index 000000000..4b267581f --- /dev/null +++ b/disconf-web/src/test/resources/log4j.properties @@ -0,0 +1,19 @@ + +log4j.rootLogger=INFO,dailyRolling,CONSOLE + +log4j.logger.org.apache.zookeeper=WARN +log4j.logger.org.springframework=INFO +log4j.logger.org.springframework.aop.framework.Cglib2AopProxy = INFO + +log4j.appender.dailyRolling=org.apache.log4j.DailyRollingFileAppender +log4j.appender.dailyRolling.File=../log/disconf-log4j.log +log4j.appender.dailyRolling.layout=org.apache.log4j.PatternLayout +log4j.appender.dailyRolling.layout.ConversionPattern=%d [%t] %-5p %-17c{2} (%13F:%L) %3x - %m%n + +log4j.appender.Threshold=WARN +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Target=System.out +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d [%t] %-5p %-17c{2} (%13F:%L) %3x - %m%n + + diff --git a/pom.xml b/pom.xml index 21327c48e..a82d4ce76 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.baidu.disconf disconf-base - 2.6.36 + 2.6.41 pom @@ -26,9 +26,9 @@ - 2.6.36 - 2.6.36 - 2.6.36 + 2.6.41 + 2.6.41 + 2.6.41 UTF-8 @@ -462,35 +462,30 @@ - - org.slf4j - slf4j-nop - 1.7.6 + com.github.tomakehurst + wiremock + 1.46 + test + + standalone org.slf4j - slf4j-api - 1.7.6 - - - - ch.qos.logback - logback-core - 1.0.9 + slf4j-log4j12 + 1.7.25 - - ch.qos.logback - logback-classic - 1.0.9 + org.slf4j + slf4j-api + 1.7.25 - log4j log4j - 1.2.14 + 1.2.17 com.sun.jmx @@ -506,21 +501,11 @@ - - - com.github.tomakehurst - wiremock - 1.46 - test - - standalone - - org.slf4j - slf4j-log4j12 - 1.4.3 + slf4j-nop + 1.7.25 + test