Răsfoiți Sursa

center多节点

roo00 6 ani în urmă
părinte
comite
04dcc3f859
100 a modificat fișierele cu 2478 adăugiri și 1403 ștergeri
  1. 1 0
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/ApplicationServletContextListener.java
  2. 0 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceAdminFactory.java
  3. 1 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceAppealInfoFactory.java
  4. 0 1
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceWorkPlaceFactory.java
  5. 3 4
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/schedule/AttendanceStatisticTask.java
  6. 3 4
      o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/schedule/MobileRecordAnalyseTask.java
  7. 132 43
      o2server/x_attendance_assemble_control/src/main/webapp/jest/describe.js
  8. 19 6
      o2server/x_attendance_assemble_control/src/main/webapp/jest/index.html
  9. 58 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/container/EntityManagerContainer.java
  10. 5 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/container/factory/PersistenceXmlHelper.java
  11. 1 12
      o2server/x_base_core_project/src/main/java/com/x/base/core/entity/JpaObject.java
  12. 33 11
      o2server/x_base_core_project/src/main/java/com/x/base/core/entity/StorageObject.java
  13. 2 6
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/AbstractContext.java
  14. 38 9
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/Application.java
  15. 53 23
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/Applications.java
  16. 60 38
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/Context.java
  17. 0 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceA.java
  18. 0 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceC.java
  19. 0 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceM.java
  20. 13 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/bean/PropertyObject.java
  21. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/cache/ApplicationCache.java
  22. 34 19
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ApplicationServer.java
  23. 22 12
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CenterServer.java
  24. 51 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CenterServers.java
  25. 55 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Collect.java
  26. 136 81
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Config.java
  27. 23 35
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CreateSample.java
  28. 0 188
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataMapping.java
  29. 0 14
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataMappings.java
  30. 101 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ExternalStorageSource.java
  31. 23 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ExternalStorageSources.java
  32. 30 30
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/LogLevel.java
  33. 34 48
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Node.java
  34. 13 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Nodes.java
  35. 76 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java
  36. 54 32
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageMapping.java
  37. 21 17
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageMappings.java
  38. 17 3
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageServer.java
  39. 10 2
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/WebServer.java
  40. 14 14
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/connection/ConnectionAction.java
  41. 10 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectConnectError.java
  42. 10 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectDisable.java
  43. 10 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectValidateFailure.java
  44. 13 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionUnsupportedMediaType.java
  45. 4 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/gson/GsonPropertyObject.java
  46. 3 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CaptchaFactory.java
  47. 4 7
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CodeFactory.java
  48. 1 2
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CollectFactory.java
  49. 228 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/StandardJaxrsAction.java
  50. 2 3
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/fireschedule/ActionExecute.java
  51. 12 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/fireschedule/ExceptionScheduleLastNotEnd.java
  52. 2 2
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/logger/Audit.java
  53. 5 5
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/logger/Logger.java
  54. 37 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/AbstractJob.java
  55. 12 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ExceptionScheduleLastNotEnd.java
  56. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/JobReportListener.java
  57. 0 207
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ReportToCenter.java
  58. 0 20
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleLocalRequest.java
  59. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleLogRequest.java
  60. 8 17
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleRequest.java
  61. 0 14
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/SchedulerFactoryProperties.java
  62. 12 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/CronTools.java
  63. 39 0
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/DateTools.java
  64. 119 26
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/DocumentTools.java
  65. 1 1
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_file_assemble_control.java
  66. 0 13
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_hotpic_assemble_control.java
  67. 0 17
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_organization_assemble_personal.java
  68. 5 49
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_processplatform_assemble_designer.java
  69. 5 49
      o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_program_center.java
  70. 13 0
      o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/gson/Foo.java
  71. 30 0
      o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/lambda/TestClient2.java
  72. 24 4
      o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/list/TestClient.java
  73. 1 0
      o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/ApplicationServletContextListener.java
  74. 3 4
      o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/SubjectReplyTotalStatisticTask.java
  75. 4 5
      o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/SubjectTotalStatisticTask.java
  76. 3 4
      o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/UserSubjectReplyPermissionStatisticTask.java
  77. 132 43
      o2server/x_bbs_assemble_control/src/main/webapp/jest/describe.js
  78. 19 6
      o2server/x_bbs_assemble_control/src/main/webapp/jest/index.html
  79. 18 0
      o2server/x_bbs_core_entity/src/main/java/com/x/bbs/entity/BBSSubjectAttachment.java
  80. 1 0
      o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/ApplicationServletContextListener.java
  81. 1 1
      o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/jaxrs/test/ActionTest1.java
  82. 3 3
      o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/schedule/AlarmTrigger.java
  83. 132 43
      o2server/x_calendar_assemble_control/src/main/webapp/jest/describe.js
  84. 19 6
      o2server/x_calendar_assemble_control/src/main/webapp/jest/index.html
  85. 1 0
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/ApplicationServletContextListener.java
  86. 2 2
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/ThisApplication.java
  87. 9 4
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/appinfo/BaseAction.java
  88. 10 4
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/ReviewService.java
  89. 27 25
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/timertask/Timertask_BatchOperationTask.java
  90. 3 4
      o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/timertask/Timertask_LogRecordCheckTask.java
  91. 132 43
      o2server/x_cms_assemble_control/src/main/webapp/jest/describe.js
  92. 19 6
      o2server/x_cms_assemble_control/src/main/webapp/jest/index.html
  93. 34 13
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/FileInfo.java
  94. 3 3
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/CalculateEntryTools.java
  95. 1 1
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/GroupEntryTools.java
  96. 2 2
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/OrderEntryTools.java
  97. 1 1
      o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/Row.java
  98. 17 19
      o2server/x_cms_core_express/src/main/java/com/x/cms/core/express/permission/CmsPermissionService.java
  99. 1 0
      o2server/x_component_assemble_control/src/main/java/com/x/component/assemble/control/ApplicationServletContextListener.java
  100. 132 43
      o2server/x_component_assemble_control/src/main/webapp/jest/describe.js

+ 1 - 0
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/ApplicationServletContextListener.java

@@ -14,6 +14,7 @@ public class ApplicationServletContextListener implements ServletContextListener
 		try {
 			ThisApplication.context = Context.concrete(servletContextEvent);
 			ThisApplication.init();
+			ThisApplication.context().regist();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 0 - 1
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceAdminFactory.java

@@ -16,7 +16,6 @@ import com.x.attendance.entity.AttendanceAdmin_;
 import com.x.base.core.project.exception.ExceptionWhen;
 /**
  * 系统配置信息表基础功能服务类
- * @author liyi
  */
 public class AttendanceAdminFactory extends AbstractFactory {
 	

+ 1 - 1
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceAppealInfoFactory.java

@@ -21,7 +21,7 @@ import com.x.base.core.project.bean.NameValueCountPair;
 import com.x.base.core.project.exception.ExceptionWhen;
 /**
  * 系统配置信息表基础功能服务类
- * @author liyi
+
  */
 public class AttendanceAppealInfoFactory extends AbstractFactory {
 	

+ 0 - 1
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/factory/AttendanceWorkPlaceFactory.java

@@ -16,7 +16,6 @@ import com.x.attendance.entity.AttendanceWorkPlace_;
 import com.x.base.core.project.exception.ExceptionWhen;
 /**
  * 工作场所信息服务类
- * @author liyi
  */
 public class AttendanceWorkPlaceFactory extends AbstractFactory {
 	

+ 3 - 4
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/schedule/AttendanceStatisticTask.java

@@ -1,12 +1,11 @@
 package com.x.attendance.assemble.control.schedule;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.x.attendance.assemble.control.service.AttendanceStatisticServiceAdv;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 
 /**
  * 定时统计代理,定时对所有的统计需求进行统计
@@ -14,11 +13,11 @@ import com.x.base.core.project.logger.LoggerFactory;
  * @author LIYI
  *
  */
-public class AttendanceStatisticTask implements Job {
+public class AttendanceStatisticTask extends AbstractJob {
 
 	private static Logger logger = LoggerFactory.getLogger(AttendanceStatisticTask.class);
  
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		AttendanceStatisticServiceAdv attendanceStatisticServiceAdv = new AttendanceStatisticServiceAdv();
 		attendanceStatisticServiceAdv.doStatistic(false);
 		logger.info("Timertask completed and excute success.");

+ 3 - 4
o2server/x_attendance_assemble_control/src/main/java/com/x/attendance/assemble/control/schedule/MobileRecordAnalyseTask.java

@@ -2,9 +2,7 @@ package com.x.attendance.assemble.control.schedule;
 
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.x.attendance.assemble.control.service.AttendanceDetailMobileAnalyseServiceAdv;
 import com.x.attendance.assemble.control.service.AttendanceDetailMobileService;
@@ -12,11 +10,12 @@ import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 
 /**
  * 定期对用户手机打卡记录进行分析
  */
-public class MobileRecordAnalyseTask implements Job {
+public class MobileRecordAnalyseTask extends AbstractJob {
 
 	private static Logger logger = LoggerFactory.getLogger(MobileRecordAnalyseTask.class);
 
@@ -25,7 +24,7 @@ public class MobileRecordAnalyseTask implements Job {
 	private AttendanceDetailMobileAnalyseServiceAdv attendanceDetailMobileAnalyseServiceAdv = new AttendanceDetailMobileAnalyseServiceAdv();
 
 	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		List<String> ids = null;
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			ids = attendanceDetailMobileService.listAllAnalyseWithStatus(emc, 0);

+ 132 - 43
o2server/x_attendance_assemble_control/src/main/webapp/jest/describe.js

@@ -1,7 +1,6 @@
 var Describe = function() {
 	// 20180730
 }
-
 Describe.splitValue = function(str) {
 	if (str) {
 		if (str.length > 0) {
@@ -10,7 +9,6 @@ Describe.splitValue = function(str) {
 	}
 	return [];
 }
-
 Describe.joinValue = function(o, split) {
 	var s = ',';
 	if (split) {
@@ -23,7 +21,6 @@ Describe.joinValue = function(o, split) {
 	}
 	return o;
 }
-
 Describe.doPost = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -59,7 +56,6 @@ Describe.doPost = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doPut = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -95,7 +91,6 @@ Describe.doPut = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doGet = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -119,7 +114,6 @@ Describe.doGet = function(address, m) {
 		window.open(address, '_blank');
 	}
 }
-
 Describe.doDelete = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -155,7 +149,6 @@ Describe.doDelete = function(address, m) {
 		});
 	}
 }
-
 Describe.writeOut = function(outs, json) {
 	if (outs && (outs.length) && json && json.data) {
 		$.each(Object.keys(json.data), function(i, k) {
@@ -164,14 +157,98 @@ Describe.writeOut = function(outs, json) {
 	}
 }
 
+Describe.createSample= function(m) {
+	var address = window.location.href;
+	address = address.substring(0,address.indexOf("/jest/"));
+	var address = address +"/"+ m.path;
+	if (m.pathParameters && m.pathParameters.length > 0) {
+		$.each(m.pathParameters, function(pi, p) {
+			address = address.replace('{' + p.name + '}', '替换参数'+pi);
+		});
+	}
+	if (m.queryParameters && m.queryParameters.length > 0) {
+		$.each(m.queryParameters, function(pi, p) {
+			var query = p.name + '=' + '替换参数'+pi;
+			if (address.indexOf("?") > 0) {
+				address += '&' + query;
+			} else {
+				address += '?' + query;
+			}
+		});
+	}
+	
+	var strSample="";
+	if (m.contentType.indexOf('application/json') > -1) {
+		  strSample =  "var data = {};" + "\n";
+			if (m.ins && m.ins.length > 0) {
+				$.each(m.ins, function(ii, i) {
+					switch (i.type) {
+					default:
+						if (i.isBaseType) {
+							if (i.isCollection) {
+								  strSample += 'data["'+i.name+'"] = ["参数1"];' + "\n";
+							} else {
+								  strSample += 'data["'+i.name+'"] = "参数";' + "\n";
+							}
+						} else {
+							      strSample += 'data["'+i.name+'"] = {"参数1":"value1","参数2":"value2"};'+"\n";
+						}
+					}
+				});
+			} else if (m.useJsonElementParameter) {
+				strSample += 'data = {"参数1":"value1","参数2":"value2"};' +"\n";
+			} else if (m.useStringParameter) {
+				strSample += 'data = "参数";'+"\n";
+			}
+			
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "dataType : 'json'" + ",\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : '"+m.contentType+ "',\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : data"+"\n";
+			strSample += "}).always(function(resultJson) {"+"\n";
+			strSample += "alert(JSON.stringify(resultJson, null, 4))" +"\n";
+			strSample += "});";
+			
+	} else {
+			strSample = "var formData = new FormData();" + "\n";
+			if (m.formParameters && m.formParameters.length > 0) {
+				$.each(m.formParameters, function(pi, p) {
+					if (p.type == "File") {
+							//formData.append(p.name, $('input[type=file]', '#formParameters')[0].files[0]);
+					strSample += 'formData.append("'+p.name+'", $("input[type=file]")[0].files[0]);' +  "\n";
+					} else {
+					strSample += 'formData.append("'+p.name+'", "参数'+pi+'");' +  "\n";
+					}
+				});
+			}
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : false,\n";
+			strSample += "processData  : false,\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : formData"+"\n";
+			strSample += "});";	
+	}
+
+	return  strSample;
+   }
+
 Describe.prototype = {
 	"load" : function() {
 		var str = '<ul>';
 		$.getJSON('../describe/describe.json?rd=' + Math.random(), function(json) {
 			$.each(json.jaxrs, function(ji, j) {
-				str += '<li>' + j.name;
+				str += '<li xtype="menu" >' + j.name;
 				$.each(j.methods, function(mi, m) {
-					str += '<ul><li><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
+					str += '<ul><li xtype="li"><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
 				});
 				str += '</li>'
 			});
@@ -182,6 +259,7 @@ Describe.prototype = {
 					$('#' + j.name + '_' + m.name).click(
 							function() {
 								$('#result').html('');
+								var sample = "";
 								var txt = '<fieldset id="method"><legend>Method</legend>';
 								txt += '<table>';
 								txt += '<tr><td>name:</td><td><a href="../describe/sources/' + m.className.replace(/\./g, '/') + '.java">' + m.name + '</a></td></tr>';
@@ -200,60 +278,63 @@ Describe.prototype = {
 											switch (p.name) {
 											case 'flag':
 											case 'id':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="(0)"/></td><td>' + p.name
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="(0)"/></td><td>' + p.name
 														+ ':' + p.description + '</td></tr>';
 												break;
 											case 'count':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="20"/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="20"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break;
 											default:
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break
 											}
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.formParameters && m.formParameters.length > 0) {
 									txt += '<fieldset id="formParameters"><legend>Form Parameter</legend>';
 									txt += '<table >';
 									$.each(m.formParameters, function(pi, p) {
 										if (p.type == "File") {
-											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>'
+											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>'
 													+ p.name + ':' + p.description + '</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.queryParameters && m.queryParameters.length > 0) {
 									txt += '<fieldset id="queryParameters"><legend>Query Parameter</legend>';
 									txt += '<table >';
 									$.each(m.queryParameters, function(pi, p) {
-										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':' + p.description
+										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':' + p.description
 												+ '</td></tr>';
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.ins && m.ins.length > 0) {
 									txt += '<fieldset id="ins"><legend>In</legend>';
 									txt += '<table>';
 									$.each(m.ins, function(ii, i) {
 										if (i.isCollection) {
-											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':' + i.description
+											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':' + i.description
 											'</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':'
+											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':'
 													+ i.description
 											'</td></tr>';
 										}
@@ -261,22 +342,26 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
+								
 								if (m.useJsonElementParameter) {
 									txt += '<fieldset><legend>JsonElement</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>json</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.useStringParameter) {
 									txt += '<fieldset><legend>String</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>string</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.outs && m.outs.length > 0) {
 									txt += '<fieldset id="outs"><legend>Out</legend>';
 									txt += '<table>';
@@ -287,7 +372,9 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								$('#content').html(txt);
+								
 								$('#' + m.name + '_' + m.type, '#method').click(function() {
 									var address = '../' + m.path;
 									if (m.pathParameters && m.pathParameters.length > 0) {
@@ -308,7 +395,6 @@ Describe.prototype = {
 									if (m.contentType.indexOf('application/json') > -1) {
 										switch (m.type) {
 										case 'POST':
-										debugger;
 											var data = {};
 											if (m.ins && m.ins.length > 0) {
 												$.each(m.ins, function(ii, i) {
@@ -321,21 +407,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -355,21 +431,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -385,6 +451,7 @@ Describe.prototype = {
 										default:
 											break;
 										}
+										
 									} else {
 										switch (m.type) {
 										case 'POST':
@@ -424,9 +491,31 @@ Describe.prototype = {
 										}
 									}
 								})
+								
+								debugger;
+							 $('#Sample').html(Describe.createSample(m));
 							});
 				});
 			});
+		 
+		  $("[xtype='menu']").click(
+				  function(event) {
+					    if(event.stopPropagation){
+						    event.stopPropagation();
+						  }else{
+						     event.cancelBubble = true;
+						  }
+					    $(this).children().toggle();
+					});
+		  $("[xtype='li']").click( function(event) {
+			    if(event.stopPropagation){
+				    event.stopPropagation();
+				  }else{
+				     event.cancelBubble = true;
+				  }
+			})
 		});
+		
+	
 	}
 }

+ 19 - 6
o2server/x_attendance_assemble_control/src/main/webapp/jest/index.html

@@ -81,21 +81,34 @@
 </script>
 </head>
 
-<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px">
+<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">
 	<table style="width: 1800px; margin: 0 auto">
 		<tr>
 			<td style="width: 350px;" valign="top">
 				<fieldset>
 					<legend>API Menu</legend>
-					<div id="menu" style="height: 850px; overflow: auto">&nbsp;</div>
+					<div id="menu" style="height: 850px; overflow: auto;">&nbsp;</div>
 				</fieldset>
 			</td>
-			<td valign="top">
-				<fieldset>
-					<legend>API Content</legend>
+			<td valign="top">			
+				<!--<fieldset>
+					<legend>Content</legend>
 					<div id="content"
 						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word">&nbsp;</div>
-				</fieldset>
+				</fieldset> -->
+				
+				<div id="content"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">&nbsp;</div>
+						
+			    <fieldset>
+					<legend>
+						Sample&nbsp;<a  id="btn_copy"  href="javascript:" data-clipboard-target="#Sample">copy</a>&nbsp;
+					</legend><div style="padding-left:12px">
+					<div id="Sample"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word; width: 1400px;">&nbsp;</div>
+						</div>
+				</fieldset>		
+						
 				<fieldset>
 					<legend>
 						Result&nbsp;<a id="btn_copy" href="javascript:" data-clipboard-target="#result">copy</a>&nbsp;

+ 58 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/container/EntityManagerContainer.java

@@ -392,6 +392,32 @@ public class EntityManagerContainer extends EntityManagerContainerBasic {
 		return new TreeList<T>(os);
 	}
 
+	public <T extends JpaObject> List<T> listEqualAndEqualAndEqual(Class<T> cls, String attribute, Object value,
+			String otherAttribute, Object otherValue, String thirdAttribute, Object thirdValue) throws Exception {
+		EntityManager em = this.get(cls);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<T> cq = cb.createQuery(cls);
+		Root<T> root = cq.from(cls);
+		cq.select(root).where(cb.and(cb.equal(root.get(attribute), value),
+				cb.equal(root.get(otherAttribute), otherValue), cb.equal(root.get(thirdAttribute), thirdValue)));
+		List<T> os = em.createQuery(cq).getResultList();
+		return new TreeList<T>(os);
+	}
+
+	public <T extends JpaObject> List<T> listEqualAndEqualAndEqualAndNotEqual(Class<T> cls, String firstAttribute,
+			Object firstValue, String secondAttribute, Object secondValue, String thirdAttribute, Object thirdValue,
+			String fourthAttribute, Object fourthValue) throws Exception {
+		EntityManager em = this.get(cls);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<T> cq = cb.createQuery(cls);
+		Root<T> root = cq.from(cls);
+		cq.select(root).where(cb.and(cb.equal(root.get(firstAttribute), firstValue),
+				cb.equal(root.get(secondAttribute), secondValue), cb.equal(root.get(thirdAttribute), thirdValue),
+				cb.notEqual(root.get(fourthAttribute), fourthValue)));
+		List<T> os = em.createQuery(cq).getResultList();
+		return new TreeList<T>(os);
+	}
+
 	public <T extends JpaObject> List<T> listEqualAndNotEqual(Class<T> cls, String equalAttribute, Object equalValue,
 			String notEqualAttribute, Object notEqualValue) throws Exception {
 		EntityManager em = this.get(cls);
@@ -657,6 +683,38 @@ public class EntityManagerContainer extends EntityManagerContainerBasic {
 		return list;
 	}
 
+	public <T extends JpaObject> List<String> idsEqualAndEqualAndEqual(Class<T> cls, String attribute, Object value,
+			String otherAttribute, Object otherValue, String thirdAttribute, Object thirdValue) throws Exception {
+		EntityManager em = this.get(cls);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<String> cq = cb.createQuery(String.class);
+		Root<T> root = cq.from(cls);
+		Predicate p = cb.equal(root.get(attribute), value);
+		p = cb.and(p, cb.equal(root.get(otherAttribute), otherValue));
+		p = cb.and(p, cb.equal(root.get(thirdAttribute), thirdValue));
+		cq.select(root.get(JpaObject.id_FIELDNAME)).where(p);
+		List<String> os = em.createQuery(cq).getResultList();
+		List<String> list = new ArrayList<>(os);
+		return list;
+	}
+
+	public <T extends JpaObject> List<String> idsEqualAndEqualAndEqualAndNotEqual(Class<T> cls, String firstAttribute,
+			Object firstValue, String secondAttribute, Object secondValue, String thirdAttribute, Object thirdValue,
+			String fourthAttribute, Object fourthValue) throws Exception {
+		EntityManager em = this.get(cls);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<String> cq = cb.createQuery(String.class);
+		Root<T> root = cq.from(cls);
+		Predicate p = cb.equal(root.get(firstAttribute), firstValue);
+		p = cb.and(p, cb.equal(root.get(secondAttribute), secondValue));
+		p = cb.and(p, cb.equal(root.get(thirdAttribute), thirdValue));
+		p = cb.and(p, cb.notEqual(root.get(fourthAttribute), fourthValue));
+		cq.select(root.get(JpaObject.id_FIELDNAME)).where(p);
+		List<String> os = em.createQuery(cq).getResultList();
+		List<String> list = new ArrayList<>(os);
+		return list;
+	}
+
 	public <T extends JpaObject> List<String> idsEqualAndNotEqual(Class<T> cls, String equalAttribute,
 			Object equalValue, String notEqualAttribute, Object notEqualValue) throws Exception {
 		EntityManager em = this.get(cls);

+ 5 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/container/factory/PersistenceXmlHelper.java

@@ -61,7 +61,7 @@ public class PersistenceXmlHelper {
 		List<String> names = new ArrayList<>();
 		String name = "";
 		try {
-			names.addAll((List<String>) Config.resource(Config.RESOUCE_CONTAINERENTITYNAMES));
+			names.addAll((List<String>) Config.resource(Config.RESOURCE_CONTAINERENTITYNAMES));
 			names = ListTools.includesExcludesWildcard(names, entities, null);
 			Document document = DocumentHelper.createDocument();
 			Element persistence = document.addElement("persistence", "http://java.sun.com/xml/ns/persistence");
@@ -139,7 +139,7 @@ public class PersistenceXmlHelper {
 		properties.put("openjpa.slice.Names",
 				StringUtils.join(Config.externalDataSources().findNamesOfContainerEntity(className), ","));
 		for (String name : Config.externalDataSources().findNamesOfContainerEntity(className)) {
-			properties.put("openjpa.slice." + name + ".ConnectionFactoryName", Config.RESOUCE_JDBC_PREFIX + name);
+			properties.put("openjpa.slice." + name + ".ConnectionFactoryName", Config.RESOURCE_JDBC_PREFIX + name);
 			properties.put("openjpa.slice." + name + ".Log", Config.externalDataSources().log(name));
 		}
 		return properties;
@@ -151,7 +151,7 @@ public class PersistenceXmlHelper {
 		properties.put("openjpa.slice.Names",
 				StringUtils.join(Config.nodes().dataServers().findNamesOfContainerEntity(className), ","));
 		for (String name : Config.nodes().dataServers().findNamesOfContainerEntity(className)) {
-			properties.put("openjpa.slice." + name + ".ConnectionFactoryName", Config.RESOUCE_JDBC_PREFIX + name);
+			properties.put("openjpa.slice." + name + ".ConnectionFactoryName", Config.RESOURCE_JDBC_PREFIX + name);
 			properties.put("openjpa.slice." + name + ".Log", Config.nodes().dataServers().log(name));
 		}
 		return properties;
@@ -180,7 +180,7 @@ public class PersistenceXmlHelper {
 			properties.put("openjpa.jdbc.Schema", JpaObject.default_schema);
 		}
 		for (String name : Config.externalDataSources().findNamesOfContainerEntity(className)) {
-			properties.put("openjpa.ConnectionFactoryName", Config.RESOUCE_JDBC_PREFIX + name);
+			properties.put("openjpa.ConnectionFactoryName", Config.RESOURCE_JDBC_PREFIX + name);
 			properties.put("openjpa.Log", Config.externalDataSources().log(name));
 			break;
 		}
@@ -191,7 +191,7 @@ public class PersistenceXmlHelper {
 		Properties properties = properties_base_single(className);
 		properties.put("openjpa.jdbc.DBDictionary", SlicePropertiesBuilder.dictionary_h2);
 		for (String name : Config.nodes().dataServers().findNamesOfContainerEntity(className)) {
-			properties.put("openjpa.ConnectionFactoryName", Config.RESOUCE_JDBC_PREFIX + name);
+			properties.put("openjpa.ConnectionFactoryName", Config.RESOURCE_JDBC_PREFIX + name);
 			properties.put("openjpa.Log", Config.nodes().dataServers().log(name));
 			break;
 		}

+ 1 - 12
o2server/x_base_core_project/src/main/java/com/x/base/core/entity/JpaObject.java

@@ -235,7 +235,7 @@ public abstract class JpaObject extends GsonPropertyObject implements Serializab
 	public static final String ORDERCOLUMNCOLUMN = "xorderColumn";
 
 	public static final String DISTINGUISHEDNAME = "distinguishedName";
-	
+
 	public static final String TYPE_STRING = "string";
 	public static final String TYPE_INTEGER = "integer";
 	public static final String TYPE_LONG = "long";
@@ -273,18 +273,7 @@ public abstract class JpaObject extends GsonPropertyObject implements Serializab
 		return ListTools.trim(values, true, true);
 	}
 
-	public Object get(String name) throws Exception {
-		return PropertyUtils.getProperty(this, name);
-	}
 
-	@SuppressWarnings("unchecked")
-	public <T> T get(String name, Class<T> clazz) throws Exception {
-		Object o = get(name);
-		if (null == o) {
-			return null;
-		}
-		return (T) o;
-	}
 
 	public int hashCode() {
 		return 31 + ((this.getId() == null) ? 0 : this.getId().hashCode());

+ 33 - 11
o2server/x_base_core_project/src/main/java/com/x/base/core/entity/StorageObject.java

@@ -6,6 +6,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URLEncoder;
 import java.util.Date;
+import java.util.Objects;
 
 import javax.persistence.MappedSuperclass;
 import javax.persistence.Transient;
@@ -21,6 +22,8 @@ import org.apache.commons.vfs2.cache.NullFilesCache;
 import org.apache.commons.vfs2.impl.StandardFileSystemManager;
 import org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder;
 import org.apache.commons.vfs2.provider.ftp.FtpFileType;
+import org.apache.commons.vfs2.provider.http.HttpFileSystemConfigBuilder;
+import org.apache.commons.vfs2.provider.webdav.WebdavFileSystemConfigBuilder;
 
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.config.StorageMapping;
@@ -72,6 +75,10 @@ public abstract class StorageObject extends SliceJpaObject {
 
 	abstract public void setLastUpdateTime(Date lastUpdateTime);
 
+	abstract public Boolean getDeepPath();
+
+	abstract public void setDeepPath(Boolean deepPath);
+
 	@Transient
 	private byte[] bytes;
 
@@ -155,7 +162,10 @@ public abstract class StorageObject extends SliceJpaObject {
 					OutputStream output = fo.getContent().getOutputStream()) {
 				length = IOUtils.copyLarge(new ByteArrayInputStream(baos.toByteArray()), output);
 				this.setLength(length);
-				manager.closeFileSystem(fo.getFileSystem());
+				if (!Objects.equals(StorageProtocol.webdav, mapping.getProtocol())) {
+					/* webdav关闭会试图去关闭commons.httpClient */
+					manager.closeFileSystem(fo.getFileSystem());
+				}
 			}
 		}
 		this.setStorage(mapping.getName());
@@ -238,20 +248,25 @@ public abstract class StorageObject extends SliceJpaObject {
 		// tar, temp, webdav, zip, cifs, mime;
 		case ftp:
 			// ftp://[ username[: password]@] hostname[: port][ relative-path]
-			prefix = "ftp://" + mapping.getUsername() + ":"
+			prefix = "ftp://" + URLEncoder.encode(mapping.getUsername(), DefaultCharset.name) + ":"
 					+ URLEncoder.encode(mapping.getPassword(), DefaultCharset.name) + "@" + mapping.getHost() + ":"
 					+ mapping.getPort();
 			break;
 		case cifs:
 			// smb://[ username[: password]@] hostname[: port][ absolute-path]
-			prefix = "smb://" + mapping.getUsername() + ":"
+			prefix = "smb://" + URLEncoder.encode(mapping.getUsername(), DefaultCharset.name) + ":"
 					+ URLEncoder.encode(mapping.getPassword(), DefaultCharset.name) + "@" + mapping.getHost() + ":"
 					+ mapping.getPort();
 			break;
+		case webdav:
+			// webdav://[ username[: password]@] hostname[: port][ absolute-path]
+			prefix = "webdav://" + URLEncoder.encode(mapping.getUsername(), DefaultCharset.name) + ":"
+					+ URLEncoder.encode(mapping.getPassword(), DefaultCharset.name) + "@" + mapping.getHost() + ":"
+					+ mapping.getPort();
 		default:
 			break;
 		}
-		return prefix;
+		return prefix + (StringUtils.isEmpty(mapping.getPrefix()) ? "" : ("/" + mapping.getPrefix()));
 	}
 
 	private FileSystemOptions getOptions(StorageMapping mapping) throws Exception {
@@ -263,7 +278,7 @@ public abstract class StorageObject extends SliceJpaObject {
 		// bzip2,file, ftp, ftps, gzip, hdfs, http, https, jar, ram, res, sftp,
 		// tar, temp, webdav, zip, cifs, mime;
 		case ftp:
-			FtpFileSystemConfigBuilder builder = FtpFileSystemConfigBuilder.getInstance();
+			FtpFileSystemConfigBuilder ftpBuilder = FtpFileSystemConfigBuilder.getInstance();
 			/*
 			 * 如果使用被动模式在阿里云centos7下会经常性出现无法连接 Caused by: java.net.ConnectException:
 			 * Connection timed out (Connection timed out) at
@@ -275,19 +290,26 @@ public abstract class StorageObject extends SliceJpaObject {
 			 * java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at
 			 * java.net.Socket.connect(Socket.java:589)
 			 */
-			builder.setPassiveMode(opts, Config.vfs().getFtp().getPassive());
+			ftpBuilder.setPassiveMode(opts, Config.vfs().getFtp().getPassive());
 			// builder.setPassiveMode(opts, false);
 			// builder.setPassiveMode(opts, true);
 			/** 强制不校验IP */
-			builder.setRemoteVerification(opts, false);
+			ftpBuilder.setRemoteVerification(opts, false);
 			// FtpFileType.BINARY is the default
-			builder.setFileType(opts, FtpFileType.BINARY);
-			builder.setConnectTimeout(opts, 10000);
-			builder.setSoTimeout(opts, 10000);
-			builder.setControlEncoding(opts, DefaultCharset.name);
+			ftpBuilder.setFileType(opts, FtpFileType.BINARY);
+			ftpBuilder.setConnectTimeout(opts, 10000);
+			ftpBuilder.setSoTimeout(opts, 10000);
+			ftpBuilder.setControlEncoding(opts, DefaultCharset.name);
 			break;
 		case cifs:
 			break;
+		case webdav:
+			WebdavFileSystemConfigBuilder webdavBuilder = (WebdavFileSystemConfigBuilder)WebdavFileSystemConfigBuilder.getInstance();
+			webdavBuilder.setConnectionTimeout(opts, 10000);
+			webdavBuilder.setSoTimeout(opts, 10000);
+			webdavBuilder.setUrlCharset(opts, DefaultCharset.name);
+			//webdavBuilder.setVersioning(opts, true);
+			break;
 		default:
 			break;
 		}

+ 2 - 6
o2server/x_base_core_project/src/main/java/com/x/base/core/project/AbstractContext.java

@@ -8,11 +8,7 @@ public abstract class AbstractContext {
 
 	protected static final String INITPARAMETER_PORJECT = "project";
 
-	public Applications applications() {
-		synchronized (this) {
-			return this.applications;
-		}
-	}
+	public abstract Applications applications() throws Exception;
 
 	protected static String getName(Class<?> clz) throws Exception {
 		Module module = clz.getAnnotation(Module.class);
@@ -31,7 +27,7 @@ public abstract class AbstractContext {
 
 	/* 模块指示类 */
 	protected Module module;
-	
+
 	public Module module() {
 		return this.module;
 	}

+ 38 - 9
o2server/x_base_core_project/src/main/java/com/x/base/core/project/Application.java

@@ -8,24 +8,47 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.project.gson.GsonPropertyObject;
+import com.x.base.core.project.schedule.ScheduleLocalRequest;
+import com.x.base.core.project.schedule.ScheduleRequest;
 
 public class Application extends GsonPropertyObject {
 
+	private String className;
 	private String name;
 	private String node;
 	private String contextPath;
 	private Integer port;
 	private String token;
 	private Boolean sslEnable;
-	private List<String> containerEntities = new ArrayList<>();
-
 	private String proxyHost;
 	private Integer proxyPort;
-
 	private Integer weight;
-
+	private Integer scheduleWeight;
 	private Date reportDate;
 
+	private List<ScheduleRequest> scheduleRequestList = new ArrayList<>();
+	private List<ScheduleLocalRequest> scheduleLocalRequestList = new ArrayList<>();
+
+	public Application() {
+
+	}
+
+	public List<ScheduleRequest> getScheduleRequestList() {
+		return scheduleRequestList;
+	}
+
+	public void setScheduleRequestList(List<ScheduleRequest> scheduleRequestList) {
+		this.scheduleRequestList = scheduleRequestList;
+	}
+
+	public List<ScheduleLocalRequest> getScheduleLocalRequestList() {
+		return scheduleLocalRequestList;
+	}
+
+	public void setScheduleLocalRequestList(List<ScheduleLocalRequest> scheduleLocalRequestList) {
+		this.scheduleLocalRequestList = scheduleLocalRequestList;
+	}
+
 	public String getUrlRoot() {
 		StringBuffer buffer = new StringBuffer();
 		if (BooleanUtils.isTrue(this.sslEnable)) {
@@ -120,14 +143,20 @@ public class Application extends GsonPropertyObject {
 		this.contextPath = contextPath;
 	}
 
- 
+	public String getClassName() {
+		return className;
+	}
+
+	public void setClassName(String className) {
+		this.className = className;
+	}
 
-	public List<String> getContainerEntities() {
-		return containerEntities;
+	public Integer getScheduleWeight() {
+		return scheduleWeight;
 	}
 
-	public void setContainerEntities(List<String> containerEntities) {
-		this.containerEntities = containerEntities;
+	public void setScheduleWeight(Integer scheduleWeight) {
+		this.scheduleWeight = scheduleWeight;
 	}
 
 }

+ 53 - 23
o2server/x_base_core_project/src/main/java/com/x/base/core/project/Applications.java

@@ -2,9 +2,10 @@ package com.x.base.core.project;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
-import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Random;
+import java.util.TreeMap;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -18,6 +19,7 @@ import com.x.base.core.project.connection.CipherConnectionAction;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.tools.DefaultCharset;
+import com.x.base.core.project.tools.ListTools;
 import com.x.base.core.project.tools.StringTools;
 
 public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList<Application>> {
@@ -28,6 +30,10 @@ public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList
 
 	private volatile String token = UUID.randomUUID().toString();
 
+	private volatile Date updateTimestamp;
+
+	private static final Random random = new Random(System.currentTimeMillis());
+
 	public String getToken() {
 		return token;
 	}
@@ -36,11 +42,12 @@ public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList
 		this.token = token;
 	}
 
-	public Application get(String className, String token) throws Exception {
+	public Application get(String className, String tokenOrNode) throws Exception {
 		List<Application> list = this.get(className);
 		if (null != list) {
 			for (Application application : list) {
-				if (StringUtils.equals(token, application.getToken())) {
+				if (StringUtils.equals(tokenOrNode, application.getToken())
+						|| StringUtils.equals(tokenOrNode, application.getNode())) {
 					return application;
 				}
 			}
@@ -134,7 +141,8 @@ public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList
 
 	public ActionResponse postQuery(Boolean xdebugger, Application application, String uri, Object body)
 			throws Exception {
-		return CipherConnectionAction.post(xdebugger, application.getUrlRoot() + CipherConnectionAction.trim(uri), 	body);
+		return CipherConnectionAction.post(xdebugger, application.getUrlRoot() + CipherConnectionAction.trim(uri),
+				body);
 	}
 
 	public ActionResponse postQuery(String applicationName, String uri, Object body) throws Exception {
@@ -195,30 +203,43 @@ public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList
 	}
 
 	public Application randomWithWeight(String className) throws Exception {
-		List<Application> availabeApplications = new ArrayList<>();
 		List<Application> list = this.get(className);
-		if (null != list) {
-			for (Application app : list) {
-				availabeApplications.add(app);
+		if (ListTools.isNotEmpty(list)) {
+			if (list.size() == 1) {
+				list.get(0);
 			}
+			int cursor = 0;
+			TreeMap<Integer, Application> tree = new TreeMap<>();
+			for (Application o : list) {
+				if (o.getWeight() > 0) {
+					cursor += o.getWeight();
+					tree.put(cursor, o);
+				}
+			}
+			Application application = tree.tailMap(random.nextInt(++cursor), true).firstEntry().getValue();
+			return application;
 		}
-		if (availabeApplications.isEmpty()) {
-			return null;
-		}
-		int total = 0;
-		for (Application application : availabeApplications) {
-			total += application.getWeight();
-		}
-		Random random = new Random();
-		int rdm = random.nextInt(total);
-		int current = 0;
-		for (Application application : availabeApplications) {
-			current += application.getWeight();
-			if (rdm <= current) {
-				return application;
+		throw new Exception("randomWithWeight error: " + className + ".");
+	}
+
+	public Application randomWithScheduleWeight(String className) throws Exception {
+		List<Application> list = this.get(className);
+		if (ListTools.isNotEmpty(list)) {
+			if (list.size() == 1) {
+				list.get(0);
 			}
+			int cursor = 0;
+			TreeMap<Integer, Application> tree = new TreeMap<>();
+			for (Application o : list) {
+				if (o.getScheduleWeight() > 0) {
+					cursor += o.getScheduleWeight();
+					tree.put(cursor, o);
+				}
+			}
+			Application application = tree.tailMap(random.nextInt(++cursor), true).firstEntry().getValue();
+			return application;
 		}
-		throw new Exception("randomWithWeight error.");
+		throw new Exception("randomWithScheduleWeight error: " + className + ".");
 	}
 
 	public static String joinQueryUri(String... parts) {
@@ -231,4 +252,13 @@ public class Applications extends ConcurrentHashMap<String, CopyOnWriteArrayList
 			}
 		}).collect(Collectors.joining("/"));
 	}
+
+	public Date updateTimestamp() {
+		return updateTimestamp;
+	}
+
+	public void updateTimestamp(Date updateTimestamp) {
+		this.updateTimestamp = updateTimestamp;
+	}
+
 }

+ 60 - 38
o2server/x_base_core_project/src/main/java/com/x/base/core/project/Context.java

@@ -1,6 +1,7 @@
 package com.x.base.core.project;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.UUID;
 
@@ -13,7 +14,6 @@ import org.apache.openjpa.enhance.PCRegistry;
 import org.quartz.CronScheduleBuilder;
 import org.quartz.DateBuilder;
 import org.quartz.DateBuilder.IntervalUnit;
-import org.quartz.Job;
 import org.quartz.JobBuilder;
 import org.quartz.JobDataMap;
 import org.quartz.JobDetail;
@@ -24,19 +24,20 @@ import org.quartz.TriggerBuilder;
 import org.quartz.impl.StdSchedulerFactory;
 import org.quartz.impl.matchers.EverythingMatcher;
 
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.project.annotation.Module;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.config.StorageMappings;
-import com.x.base.core.project.connection.ActionResponse;
-import com.x.base.core.project.connection.CipherConnectionAction;
+import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.jaxrs.WrapClearCacheRequest;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
 import com.x.base.core.project.queue.AbstractQueue;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.schedule.JobReportListener;
-import com.x.base.core.project.schedule.ReportToCenter;
 import com.x.base.core.project.schedule.ScheduleLocalRequest;
 import com.x.base.core.project.schedule.ScheduleRequest;
 import com.x.base.core.project.schedule.SchedulerFactoryProperties;
@@ -111,7 +112,6 @@ public class Context extends AbstractContext {
 	}
 
 //	/* Storage资源 */
-//	private volatile StorageMappings storageMappings;
 
 	public StorageMappings storageMappings() throws Exception {
 		return Config.storageMappings();
@@ -131,6 +131,13 @@ public class Context extends AbstractContext {
 		return this.weight;
 	}
 
+	/* 应用的权重 */
+	private volatile Integer scheduleWeight;
+
+	public Integer scheduleWeight() {
+		return this.scheduleWeight;
+	}
+
 	private Boolean sslEnable;
 
 	public Boolean sslEnable() {
@@ -152,6 +159,22 @@ public class Context extends AbstractContext {
 		return this.clearCacheRequestQueue;
 	}
 
+	private volatile Date applicationsTimestamp = null;
+
+	public Applications applications() throws Exception {
+		if (null != Config.resource_node_applicationsTimestamp()) {
+			if (null == this.applicationsTimestamp
+					|| (this.applicationsTimestamp.before(Config.resource_node_applicationsTimestamp()))) {
+				synchronized (this) {
+					this.applications = XGsonBuilder.instance().fromJson(Config.resource_node_applications(),
+							Applications.class);
+					this.applicationsTimestamp = Config.resource_node_applicationsTimestamp();
+				}
+			}
+		}
+		return this.applications;
+	}
+
 	/* 队列 */
 	private List<AbstractQueue<?>> queues;
 
@@ -164,17 +187,6 @@ public class Context extends AbstractContext {
 		this.scheduler.start();
 	}
 
-//	/** 可以自定义缓存清空消息处理器 */
-//	public static Context concrete(ServletContextEvent servletContextEvent,
-//			AbstractQueue<WrapClearCacheRequest> clearCacheRequestQueue) throws Exception {
-//		Context context = concrete(servletContextEvent);
-//		if (null != clearCacheRequestQueue) {
-//			context.clearCacheRequestQueue = clearCacheRequestQueue;
-//			context.startQueue(clearCacheRequestQueue);
-//		}
-//		return context;
-//	}
-
 	public static Context concrete(ServletContextEvent servletContextEvent) throws Exception {
 		/* 强制忽略ssl服务器认证 */
 		SslTools.ignoreSsl();
@@ -182,22 +194,44 @@ public class Context extends AbstractContext {
 		Context context = new Context();
 		context.contextPath = servletContext.getContextPath();
 		context.clazz = Class.forName(servletContext.getInitParameter(INITPARAMETER_PORJECT));
-//		context.clazzInstance = (Deployable) context.clazz.newInstance();
 		context.module = context.clazz.getAnnotation(Module.class);
 		context.name = getName(context.clazz);
 		context.path = servletContext.getRealPath("");
 		context.servletContext = servletContext;
 		context.servletContextName = servletContext.getServletContextName();
 		context.weight = Config.currentNode().getApplication().weight(context.clazz);
+		context.scheduleWeight = Config.currentNode().getApplication().scheduleWeight(context.clazz);
 		context.sslEnable = Config.currentNode().getApplication().getSslEnable();
 		context.initDatas();
-		context.scheduleLocal(ReportToCenter.class, 0, ReportToCenter.INTERVAL);
 		servletContext.setAttribute(context.getClass().getName(), context);
 		context.initialized = true;
+		/* 20190927新注册机制 */
+		// registApplication(context);
 		return context;
 	}
 
-	public <T extends Job> void scheduleLocal(Class<T> cls, String cron) throws Exception {
+	/* 20190927新注册机制 */
+	public void regist() throws Exception {
+		Application application = new Application();
+		application.setClassName(this.clazz().getName());
+		application.setName(this.name());
+		application.setNode(Config.node());
+		application.setContextPath(this.contextPath());
+		application.setPort(Config.currentNode().getApplication().getPort());
+		application.setSslEnable(this.sslEnable());
+		application.setProxyHost(Config.currentNode().getApplication().getProxyHost());
+		application.setProxyPort(Config.currentNode().getApplication().getProxyPort());
+		application.setWeight(this.weight());
+		application.setScheduleWeight(this.scheduleWeight());
+		application.setScheduleLocalRequestList(this.scheduleLocalRequestList);
+		application.setScheduleRequestList(this.scheduleRequestList);
+		JsonElement jsonElement = XGsonBuilder.instance().toJsonTree(application);
+		JsonObject jsonObject = jsonElement.getAsJsonObject();
+		jsonObject.addProperty("type", "registApplication");
+		Config.resource_node_eventQueue().put(jsonObject);
+	}
+
+	public <T extends AbstractJob> void scheduleLocal(Class<T> cls, String cron) throws Exception {
 		JobDataMap jobDataMap = new JobDataMap();
 		jobDataMap.put("context", this);
 		JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(cls.getName(), clazz.getName())
@@ -208,7 +242,7 @@ public class Context extends AbstractContext {
 		this.scheduleLocalRequestList.add(new ScheduleLocalRequest(jobDetail, cron, null, null));
 	}
 
-	public <T extends Job> void scheduleLocal(Class<T> cls, Trigger existTrigger) throws Exception {
+	public <T extends AbstractJob> void scheduleLocal(Class<T> cls, Trigger existTrigger) throws Exception {
 		JobDataMap jobDataMap = new JobDataMap();
 		jobDataMap.put("context", this);
 		JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(cls.getName(), clazz.getName())
@@ -219,7 +253,7 @@ public class Context extends AbstractContext {
 		this.scheduleLocalRequestList.add(new ScheduleLocalRequest(jobDetail, null, null, null));
 	}
 
-	public <T extends Job> void scheduleLocal(Class<T> cls, Integer delay, Integer interval) throws Exception {
+	public <T extends AbstractJob> void scheduleLocal(Class<T> cls, Integer delay, Integer interval) throws Exception {
 		JobDataMap jobDataMap = new JobDataMap();
 		jobDataMap.put("context", this);
 		JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(cls.getName(), clazz.getName())
@@ -232,24 +266,24 @@ public class Context extends AbstractContext {
 		this.scheduleLocalRequestList.add(new ScheduleLocalRequest(jobDetail, null, delay, interval));
 	}
 
-	public <T extends Job> void scheduleLocal(Class<T> cls) throws Exception {
+	public <T extends AbstractJob> void scheduleLocal(Class<T> cls, Integer delay) throws Exception {
 		/* 需要单独生成一个独立任务,保证group和预约的任务不重复 */
 		String group = StringTools.uniqueToken();
 		JobDataMap jobDataMap = new JobDataMap();
 		jobDataMap.put("context", this);
 		JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(cls.getName(), group).usingJobData(jobDataMap)
 				.withDescription(Config.node()).build();
-		/* 经过测试0代表不重复,运行一次 */
+		/* 经过测试0代表不重复,运行一次 */
 		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(cls.getName(), group)
-				.withDescription("scheduleLocal")
+				.withDescription("scheduleLocal").startAt(DateBuilder.futureDate(delay, IntervalUnit.SECOND))
 				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).withRepeatCount(0))
 				.build();
 		scheduler.scheduleJob(jobDetail, trigger);
 	}
 
 	/* 统一排程任务需要延时90秒,等待instrument启动,每次间隔不能少于5分钟 */
-	public <T extends Job> void schedule(Class<T> clz, String cron) throws Exception {
-		this.scheduleRequestList.add(new ScheduleRequest(clz, this.clazz.getName(), Config.node(), cron));
+	public <T extends AbstractJob> void schedule(Class<T> clz, String cron) throws Exception {
+		this.scheduleRequestList.add(new ScheduleRequest(clz, Config.node(), cron));
 	}
 
 	public void startQueue(AbstractQueue<?> queue) {
@@ -257,18 +291,6 @@ public class Context extends AbstractContext {
 		queue.start();
 	}
 
-	public void loadApplications() {
-		try {
-			synchronized (this) {
-				ActionResponse response = CipherConnectionAction.get(false,
-						Config.x_program_centerUrlRoot() + "applications");
-				this.applications = response.getData(Applications.class);
-			}
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
 	private void initDatas() throws Exception {
 		if (ArrayUtils.isNotEmpty(this.module.containerEntities())) {
 			logger.print("{} loading datas, entity size:{}.", this.clazz.getName(),

+ 0 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceA.java

@@ -1,5 +0,0 @@
-package com.x.base.core.project;
-
-public abstract class ServiceA extends Deployable {
- 
-}

+ 0 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceC.java

@@ -1,5 +0,0 @@
-package com.x.base.core.project;
-
-public abstract class ServiceC extends Deployable {
-	 
-}

+ 0 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/ServiceM.java

@@ -1,5 +0,0 @@
-package com.x.base.core.project;
-
-public abstract class ServiceM extends Deployable {
-	 
-}

+ 13 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/bean/PropertyObject.java

@@ -51,4 +51,17 @@ public abstract class PropertyObject {
 		}
 	}
 
+	public final Object get(String name) throws Exception {
+		return PropertyUtils.isReadable(this, name) ? PropertyUtils.getProperty(this, name) : null;
+	}
+
+	@SuppressWarnings("unchecked")
+	public final <T> T get(String name, Class<T> clazz) throws Exception {
+		Object o = get(name);
+		if (null == o) {
+			return null;
+		}
+		return (T) o;
+	}
+
 }

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/cache/ApplicationCache.java

@@ -191,7 +191,7 @@ public class ApplicationCache extends AbstractApplicationCache {
 					if (wi instanceof StopNotifyThreadSignal) {
 						break out;
 					} else {
-						String url = Config.x_program_centerUrlRoot() + "cachedispatch";
+						String url = Config.url_x_program_center_jaxrs("cachedispatch");
 						CipherConnectionAction.put(false, url, wi);
 					}
 				} catch (Exception e) {

+ 34 - 19
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ApplicationServer.java

@@ -6,8 +6,6 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.project.annotation.FieldDescribe;
-import com.x.base.core.project.gson.GsonPropertyObject;
-import com.x.base.core.project.tools.Host;
 
 public class ApplicationServer extends ConfigObject {
 
@@ -26,12 +24,14 @@ public class ApplicationServer extends ConfigObject {
 		this.includes = new CopyOnWriteArrayList<String>();
 		this.excludes = new CopyOnWriteArrayList<String>();
 		this.weights = new CopyOnWriteArrayList<NameWeightPair>();
+		this.scheduleWeights = new CopyOnWriteArrayList<NameWeightPair>();
 
 	}
 
 	private static final Integer default_port = 20020;
 	private static final Integer default_scanInterval = 0;
 	public static final Integer default_weight = 100;
+	public static final Integer default_scheduleWeight = 100;
 
 	@FieldDescribe("是否启用")
 	private Boolean enable;
@@ -39,9 +39,9 @@ public class ApplicationServer extends ConfigObject {
 	private Integer port;
 	@FieldDescribe("是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.")
 	private Boolean sslEnable;
-	@FieldDescribe("代理主机,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
+	@FieldDescribe("代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
 	private String proxyHost;
-	@FieldDescribe("代理端口,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
+	@FieldDescribe("代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
 	private Integer proxyPort;
 	@FieldDescribe("每次启动是否重载全部应用.")
 	private Boolean redeploy;
@@ -51,8 +51,10 @@ public class ApplicationServer extends ConfigObject {
 	private CopyOnWriteArrayList<String> includes;
 	@FieldDescribe("选择不承载的应用,和includes的值配合使用可以选择或者排除承载的应用,可以使用*作为通配符.")
 	private CopyOnWriteArrayList<String> excludes;
-	@FieldDescribe("设置应用的权重,在集群环境中,一个应用可以部署多个实例提供负载均衡.通过合计占比来分配应用占比.")
+	@FieldDescribe("设置应用的Web访问权重,在集群环境中,一个应用可以部署多个实例提供负载均衡.通过合计占比来分配应用占比.")
 	private CopyOnWriteArrayList<NameWeightPair> weights;
+	@FieldDescribe("设置应用的定时任务权重,在集群环境中,一个应用可以部署多个实例提供负载均衡.通过合计占比来分配应用占比.")
+	private CopyOnWriteArrayList<NameWeightPair> scheduleWeights;
 
 	public Integer getScanInterval() {
 		if (null != this.scanInterval && this.scanInterval > 0) {
@@ -61,6 +63,33 @@ public class ApplicationServer extends ConfigObject {
 		return default_scanInterval;
 	}
 
+	public CopyOnWriteArrayList<NameWeightPair> getWeights() {
+		if (null == this.weights) {
+			this.weights = new CopyOnWriteArrayList<NameWeightPair>();
+		}
+		return this.weights;
+	}
+
+	public CopyOnWriteArrayList<NameWeightPair> getScheduleWeights() {
+		if (null == this.scheduleWeights) {
+			this.scheduleWeights = new CopyOnWriteArrayList<NameWeightPair>();
+		}
+		return this.scheduleWeights;
+	}
+
+	public Integer weight(Class<?> clazz) {
+		NameWeightPair pair = this.weights.stream().filter(p -> StringUtils.equals(p.getName(), clazz.getName()))
+				.findFirst().orElse(new NameWeightPair(clazz.getName(), default_weight));
+		return pair.getWeight();
+	}
+
+	public Integer scheduleWeight(Class<?> clazz) {
+		NameWeightPair pair = this.scheduleWeights.stream()
+				.filter(p -> StringUtils.equals(p.getName(), clazz.getName())).findFirst()
+				.orElse(new NameWeightPair(clazz.getName(), default_scheduleWeight));
+		return pair.getWeight();
+	}
+
 	public class NameWeightPair {
 
 		private String name;
@@ -170,18 +199,4 @@ public class ApplicationServer extends ConfigObject {
 		this.excludes = excludes;
 	}
 
-	public CopyOnWriteArrayList<NameWeightPair> getWeights() {
-		return weights;
-	}
-
-	public void setWeights(CopyOnWriteArrayList<NameWeightPair> weights) {
-		this.weights = weights;
-	}
-
-	public Integer weight(Class<?> clazz) {
-		NameWeightPair pair = this.weights.stream().filter(p -> StringUtils.equals(p.getName(), clazz.getName()))
-				.findFirst().orElse(new NameWeightPair(clazz.getName(), default_weight));
-		return pair.getWeight();
-	}
-
 }

+ 22 - 12
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CenterServer.java

@@ -13,18 +13,21 @@ import com.x.base.core.project.tools.DefaultCharset;
 
 public class CenterServer extends ConfigObject {
 
+	private static final Boolean default_enable = true;
 	private static final Integer default_port = 20030;
 	private static final Integer default_scanInterval = 0;
 	private static final Boolean default_configApiEnable = true;
+	private static final Integer default_order = 0;
 
 	public static CenterServer defaultInstance() {
 		return new CenterServer();
 	}
 
 	public CenterServer() {
+		this.enable = default_enable;
 		this.sslEnable = false;
 		this.redeploy = true;
-		// this.host = "";
+		this.order = default_order;
 		this.port = default_port;
 		this.httpProtocol = "";
 		this.proxyHost = "";
@@ -35,17 +38,20 @@ public class CenterServer extends ConfigObject {
 
 	@FieldDescribe("是否启用")
 	private Boolean enable;
+	@FieldDescribe("center节点顺序,顺序排列0,1,2...")
+	private Integer order;
 	@FieldDescribe("是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.")
 	private Boolean sslEnable;
 	@FieldDescribe("每次启动是否重新部署所有应用.")
 	private Boolean redeploy;
 	@FieldDescribe("端口,center服务器端口,默认20030")
 	private Integer port;
+
 	@FieldDescribe("对外http访问协议,http/https")
 	private String httpProtocol;
-	@FieldDescribe("代理主机,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
+	@FieldDescribe("代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
 	private String proxyHost;
-	@FieldDescribe("代理端口,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
+	@FieldDescribe("代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
 	private Integer proxyPort;
 	@FieldDescribe("重新扫描war包时间间隔(秒)")
 	private Integer scanInterval;
@@ -58,6 +64,10 @@ public class CenterServer extends ConfigObject {
 		return configApiEnable == null ? default_configApiEnable : this.configApiEnable;
 	}
 
+	public Boolean getEnable() {
+		return enable == null ? default_enable : this.enable;
+	}
+
 	public String getHttpProtocol() {
 		return StringUtils.equals("https", this.httpProtocol) ? "https" : "http";
 	}
@@ -102,6 +112,15 @@ public class CenterServer extends ConfigObject {
 		return this.config;
 	}
 
+	public Integer getOrder() {
+		return order == null ? default_order : this.order;
+	}
+
+	public void save() throws Exception {
+		File file = new File(Config.base(), Config.PATH_CONFIG_CENTERSERVER);
+		FileUtils.write(file, XGsonBuilder.toJson(this), DefaultCharset.charset);
+	}
+
 	public void setSslEnable(Boolean sslEnable) {
 		this.sslEnable = sslEnable;
 	}
@@ -134,13 +153,4 @@ public class CenterServer extends ConfigObject {
 		this.httpProtocol = httpProtocol;
 	}
 
-	public void save() throws Exception {
-		File file = new File(Config.base(), Config.PATH_CONFIG_CENTERSERVER);
-		FileUtils.write(file, XGsonBuilder.toJson(this), DefaultCharset.charset);
-	}
-
-	public void setConfigApiEnable(Boolean configApiEnable) {
-		this.configApiEnable = configApiEnable;
-	}
-
 }

+ 51 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CenterServers.java

@@ -0,0 +1,51 @@
+package com.x.base.core.project.config;
+
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.apache.commons.collections4.set.ListOrderedSet;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+
+public class CenterServers extends ConcurrentSkipListMap<String, CenterServer> {
+
+	private static final long serialVersionUID = 220144952029277793L;
+
+	public CenterServers() {
+		super();
+	}
+
+	public CenterServers(Nodes nodeConfigs) {
+		for (Entry<String, Node> o : nodeConfigs.entrySet()) {
+			CenterServer server = o.getValue().getCenter();
+			if ((null != server) && BooleanUtils.isTrue(server.getEnable())) {
+				this.put(o.getKey(), server);
+			}
+		}
+	}
+
+	public ListOrderedSet<Entry<String, CenterServer>> orderedEntrySet() {
+		ListOrderedSet<Entry<String, CenterServer>> set = new ListOrderedSet<>();
+		this.entrySet().stream().sorted((o1, o2) -> {
+			return o1.getValue().getOrder() - o2.getValue().getOrder();
+		}).forEachOrdered(o -> {
+			set.add(o);
+		});
+		return set;
+	}
+
+	public CenterServer first() {
+
+		ListOrderedSet<Entry<String, CenterServer>> set = orderedEntrySet();
+
+		if (set.isEmpty()) {
+			return null;
+		} else {
+			return set.get(0).getValue();
+		}
+
+	}
+
+	public CenterServer pirmary() throws Exception {
+		return this.get(Config.resource_node_centersPirmaryNode());
+	}
+}

+ 55 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Collect.java

@@ -1,13 +1,23 @@
 package com.x.base.core.project.config;
 
 import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.connection.ConnectionAction;
+import com.x.base.core.project.exception.ExceptionCollectConnectError;
+import com.x.base.core.project.exception.ExceptionCollectDisable;
+import com.x.base.core.project.exception.ExceptionCollectValidateFailure;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.tools.DefaultCharset;
 
@@ -144,6 +154,51 @@ public class Collect extends ConfigObject {
 		this.server = server;
 	}
 
+	public boolean validate()
+			throws ExceptionCollectConnectError, ExceptionCollectDisable, ExceptionCollectValidateFailure, Exception {
+
+		if (Config.collect().getEnable()) {
+			throw new ExceptionCollectDisable();
+		}
+
+		try {
+			URL url = new URL(this.url("/o2_collect_assemble/jaxrs/collect/validate"));
+			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+			connection.setRequestProperty(ConnectionAction.Access_Control_Allow_Credentials,
+					ConnectionAction.Access_Control_Allow_Credentials_Value);
+			connection.setRequestProperty(ConnectionAction.Access_Control_Allow_Headers,
+					ConnectionAction.Access_Control_Allow_Headers_Value);
+			connection.setRequestProperty(ConnectionAction.Access_Control_Allow_Methods,
+					ConnectionAction.Access_Control_Allow_Methods_Value);
+			connection.setRequestProperty(ConnectionAction.Cache_Control, ConnectionAction.Cache_Control_Value);
+			connection.setRequestProperty(ConnectionAction.Content_Type, ConnectionAction.Content_Type_Value);
+			connection.setRequestMethod("POST");
+			connection.setUseCaches(false);
+			connection.setDoOutput(true);
+			connection.setDoInput(true);
+			connection.connect();
+			try (OutputStream output = connection.getOutputStream()) {
+				String req = "{\"name\":\"" + Config.collect().getName() + "\",\"password\":\""
+						+ Config.collect().getPassword() + "\"}";
+				IOUtils.write(req, output, StandardCharsets.UTF_8);
+			}
+			if (200 != connection.getResponseCode()) {
+				throw new ExceptionCollectValidateFailure();
+			}
+			try (InputStream input = connection.getInputStream()) {
+				byte[] buffer = IOUtils.toByteArray(input);
+				String value = new String(buffer, DefaultCharset.name);
+				if (!StringUtils.contains(value, "success")) {
+					throw new ExceptionCollectValidateFailure();
+				}
+			}
+			connection.disconnect();
+		} catch (Exception e) {
+			throw new ExceptionCollectConnectError();
+		}
+		return true;
+	}
+
 	public String url() {
 		String url = this.getSslEnable() ? "https://" : "http://";
 		url += this.getServer();

+ 136 - 81
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Config.java

@@ -2,7 +2,12 @@ package com.x.base.core.project.config;
 
 import java.io.File;
 import java.io.FileFilter;
-import java.util.concurrent.ConcurrentHashMap;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.LinkedBlockingQueue;
 
 import javax.naming.InitialContext;
 import javax.ws.rs.core.MediaType;
@@ -14,8 +19,10 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.eclipse.jetty.http.MimeTypes;
 
+import com.google.gson.JsonElement;
 import com.x.base.core.project.x_program_center;
 import com.x.base.core.project.tools.BaseTools;
+import com.x.base.core.project.tools.DefaultCharset;
 import com.x.base.core.project.tools.Host;
 import com.x.base.core.project.tools.NumberTools;
 
@@ -30,6 +37,7 @@ public class Config {
 	public static final String PATH_LOCAL_NODE = "local/node.cfg";
 	public static final String PATH_CONFIG_TOKEN = "config/token.json";
 	public static final String PATH_CONFIG_EXTERNALDATASOURCES = "config/externalDataSources.json";
+	public static final String PATH_CONFIG_EXTERNALSTORAGESOURCES = "config/externalStorageSources.json";
 	public static final String PATH_CONFIG_ADMINISTRATOR = "config/administrator.json";
 	public static final String PATH_CONFIG_PERSON = "config/person.json";
 	public static final String PATH_CONFIG_MEETING = "config/meeting.json";
@@ -94,19 +102,26 @@ public class Config {
 	public static final String DIR_STORE = "store";
 	public static final String DIR_STORE_JARS = "store/jars";
 
-	public static final String RESOUCE_CONTAINERENTITIES = "containerEntities";
+	public static final String RESOURCE_CONTAINERENTITIES = "containerEntities";
 
-	public static final String RESOUCE_CONTAINERENTITYNAMES = "containerEntityNames";
+	public static final String RESOURCE_CONTAINERENTITYNAMES = "containerEntityNames";
 
-	public static final String RESOUCE_STORAGECONTAINERENTITYNAMES = "storageContainerEntityNames";
+	public static final String RESOURCE_STORAGECONTAINERENTITYNAMES = "storageContainerEntityNames";
 
-	public static final String RESOUCE_JDBC_PREFIX = "jdbc/";
+	public static final String RESOURCE_JDBC_PREFIX = "jdbc/";
 
-	public static final String RESOUCE_AUDITLOGPRINTSTREAM = "auditLogPrintStream";
+	public static final String RESOURCE_AUDITLOGPRINTSTREAM = "auditLogPrintStream";
 
 	// public static final String RESOUCE_CONFIG = "config";
 
-	public static final String RESOUCE_NODE = "node";
+	public static final String RESOURCE_NODE_PREFIX = "node/";
+	public static final String RESOURCE_NODE_EVENTQUEUE = RESOURCE_NODE_PREFIX + "eventQueue";
+	public static final String RESOURCE_NODE_EVENTQUEUEEXECUTOR = RESOURCE_NODE_PREFIX + "eventQueueExecutor";
+	public static final String RESOURCE_NODE_APPLICATIONS = RESOURCE_NODE_PREFIX + "applications";
+	public static final String RESOURCE_NODE_APPLICATIONSTIMESTAMP = RESOURCE_NODE_PREFIX + "applicationsTimestamp";
+	public static final String RESOURCE_NODE_CENTERSPRIMARYNODE = RESOURCE_NODE_PREFIX + "centersPrimaryNode";
+	public static final String RESOURCE_NODE_CENTERSPRIMARYPORT = RESOURCE_NODE_PREFIX + "centersPrimaryPort";
+	public static final String RESOURCE_NODE_CENTERSPRIMARYSSLENABLE = RESOURCE_NODE_PREFIX + "centersPrimarySslEnable";
 
 	private static final String DEFAULT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCWcVZIS57VeOUzi8c01WKvwJK9uRe6hrGTUYmF6J/pI6/UvCbdBWCoErbzsBZOElOH8Sqal3vsNMVLjPYClfoDyYDaUlakP3ldfnXJzAFJVVubF53KadG+fwnh9ZMvxdh7VXVqRL3IQBDwGgzX4rmSK+qkUJjc3OkrNJPB7LLD8QIDAQAB";
 	private static final String DEFAULT_PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJZxVkhLntV45TOLxzTVYq/Akr25F7qGsZNRiYXon+kjr9S8Jt0FYKgStvOwFk4SU4fxKpqXe+w0xUuM9gKV+gPJgNpSVqQ/eV1+dcnMAUlVW5sXncpp0b5/CeH1ky/F2HtVdWpEvchAEPAaDNfiuZIr6qRQmNzc6Ss0k8HsssPxAgMBAAECgYAWtRy05NUgm5Lc6Og0jVDL/mEnydxPBy2ectwzHh2k7wIHNi8XhUxFki2TMqzrM9Dv3/LySpMl4AE3mhs34LNPy6F+MwyF5X7j+2Y6MflJyeb9HNyT++viysQneoOEiOk3ghxF2/GPjpiEF79wSp+1YKTxRAyq7ypV3t35fGOOEQJBANLDPWl8b5c3lrcz/dTamMjHbVamEyX43yzQOphzkhYsz4pruATzTxU+z8/zPdEqHcWWV39CP3xu3EYNcAhxJW8CQQC2u7PF5Xb1xYRCsmIPssFxil64vvdUadSxl7GLAgjQ9ULyYWB24KObCEzLnPcT8Pf2Q0YQOixxa/78FuzmgbyfAkA7ZFFV/H7lugB6t+f7p24OhkRFep9CwBMD6dnZRBgSr6X8d8ZvfrD2Z7DgBMeSva+OEoOtlNmXExZ3lynO9zN5AkAVczEmIMp3DSl6XtAuAZC9kD2QODJ2QToLYsAfjiyUwsWKCC43piTuVOoW2KUUPSwOR1VZIEsJQWEcHGDQqhgHAkAeZ7a6dVRZFdBwKA0ADjYCufAW2cIYiVDQBJpgB+kiLQflusNOCBK0FT3lg8BdUSy2D253Ih6l3lbaM/4M7DFQ";
@@ -230,7 +245,7 @@ public class Config {
 	public static File dir_jvm_linux() throws Exception {
 		return new File(base(), DIR_JVM_LINUX);
 	}
-	
+
 	public static File dir_jvm_neokylin_loongson() throws Exception {
 		return new File(base(), DIR_JVM_NEOKYLIN_LOONGSON);
 	}
@@ -301,48 +316,6 @@ public class Config {
 		return dir;
 	}
 
-//	public static File dir_local_temp_dynamic_src() throws Exception {
-//		return dir_local_temp_dynamic_src(false);
-//	}
-//
-//	public static File dir_local_temp_dynamic_src(Boolean force) throws Exception {
-//		File dir = new File(base(), DIR_LOCAL_TEMP_DYNAMIC_SRC);
-//		if (force) {
-//			if ((!dir.exists()) || dir.isFile()) {
-//				FileUtils.forceMkdir(dir);
-//			}
-//		}
-//		return dir;
-//	}
-
-//	public static File dir_local_temp_dynamic_target() throws Exception {
-//		return dir_local_temp_dynamic_target(false);
-//	}
-//
-//	public static File dir_local_temp_dynamic_target(Boolean force) throws Exception {
-//		File dir = new File(base(), DIR_LOCAL_TEMP_DYNAMIC_TARGET);
-//		if (force) {
-//			if ((!dir.exists()) || dir.isFile()) {
-//				FileUtils.forceMkdir(dir);
-//			}
-//		}
-//		return dir;
-//	}
-
-//	public static File dir_local_temp_dynamic_resources() throws Exception {
-//		return dir_local_temp_dynamic_resources(false);
-//	}
-//
-//	public static File dir_local_temp_dynamic_resources(Boolean force) throws Exception {
-//		File dir = new File(base(), DIR_LOCAL_TEMP_DYNAMIC_RESOURCES);
-//		if (force) {
-//			if ((!dir.exists()) || dir.isFile()) {
-//				FileUtils.forceMkdir(dir);
-//			}
-//		}
-//		return dir;
-//	}
-
 	public static File dir_logs() throws Exception {
 		return new File(base(), DIR_LOGS);
 	}
@@ -518,6 +491,14 @@ public class Config {
 						Node o = Node.defaultInstance();
 						nodes.put(node(), o);
 					}
+					/* 20191009兼容centerServer */
+					CenterServer c = BaseTools.readObject(PATH_CONFIG_CENTERSERVER, CenterServer.class);
+					if (null != c) {
+						for (Node n : nodes.values()) {
+							n.setCenter(c);
+						}
+					}
+					/* 20191009兼容centerServer end */
 					instance().nodes = nodes;
 				}
 			}
@@ -560,6 +541,24 @@ public class Config {
 		return instance().externalDataSources;
 	}
 
+	private ExternalStorageSources externalStorageSources;
+
+	public static ExternalStorageSources externalStorageSources() throws Exception {
+		if (null == instance().externalStorageSources) {
+			synchronized (Config.class) {
+				if (null == instance().externalStorageSources) {
+					ExternalStorageSources obj = BaseTools.readObject(PATH_CONFIG_EXTERNALSTORAGESOURCES,
+							ExternalStorageSources.class);
+					if (null == obj) {
+						obj = ExternalStorageSources.defaultInstance();
+					}
+					instance().externalStorageSources = obj;
+				}
+			}
+		}
+		return instance().externalStorageSources;
+	}
+
 	private String publicKey;
 
 	public static String publicKey() throws Exception {
@@ -650,23 +649,6 @@ public class Config {
 		return instance().workTime;
 	}
 
-	public CenterServer centerServer;
-
-	public static CenterServer centerServer() throws Exception {
-		if (null == instance().centerServer) {
-			synchronized (Config.class) {
-				if (null == instance().centerServer) {
-					CenterServer obj = BaseTools.readObject(PATH_CONFIG_CENTERSERVER, CenterServer.class);
-					if (null == obj) {
-						obj = CenterServer.defaultInstance();
-					}
-					instance().centerServer = obj;
-				}
-			}
-		}
-		return instance().centerServer;
-	}
-
 	public Collect collect;
 
 	public static Collect collect() throws Exception {
@@ -787,7 +769,13 @@ public class Config {
 		if (null == instance().storageMappings) {
 			synchronized (Config.class) {
 				if (null == instance().storageMappings) {
-					instance().storageMappings = new StorageMappings(nodes());
+					ExternalStorageSources obj = BaseTools.readObject(PATH_CONFIG_EXTERNALSTORAGESOURCES,
+							ExternalStorageSources.class);
+					if ((obj != null)) {
+						instance().storageMappings = new StorageMappings(obj);
+					} else {
+						instance().storageMappings = new StorageMappings(nodes());
+					}
 				}
 			}
 		}
@@ -815,22 +803,29 @@ public class Config {
 		return nodes().get(node());
 	}
 
-	public static String x_program_centerUrlRoot() throws Exception {
-		String primary = nodes().primaryCenterNode();
+	public static String url_x_program_center_jaxrs(String... paths) throws Exception {
+		String n = resource_node_centersPirmaryNode();
+		Integer p = resource_node_centersPirmaryPort();
+		Boolean s = resource_node_centersPirmarySslEnable();
 		StringBuffer buffer = new StringBuffer();
-		if (centerServer().getSslEnable()) {
-			buffer.append("https://").append(primary);
-			if (!NumberTools.valueEuqals(Config.centerServer().getPort(), 443)) {
-				buffer.append(":").append(Config.centerServer().getPort());
+		if (s) {
+			buffer.append("https://").append(n);
+			if (!NumberTools.valueEuqals(p, 443)) {
+				buffer.append(":").append(p);
 			}
 		} else {
-			buffer.append("http://").append(primary);
-			if (!NumberTools.valueEuqals(Config.centerServer().getPort(), 80)) {
-				buffer.append(":").append(Config.centerServer().getPort());
+			buffer.append("http://").append(n);
+			if (!NumberTools.valueEuqals(p, 80)) {
+				buffer.append(":").append(p);
 			}
 		}
 		buffer.append("/").append(x_program_center.class.getSimpleName());
 		buffer.append("/jaxrs/");
+		List<String> os = new ArrayList<>();
+		for (String path : paths) {
+			os.add(URLEncoder.encode(StringUtils.strip(path, "/"), DefaultCharset.name));
+		}
+		buffer.append(StringUtils.join(os, "/"));
 		return buffer.toString();
 	}
 
@@ -1061,16 +1056,76 @@ public class Config {
 	}
 
 	public static Object resource_jdbc(String name) throws Exception {
-		return initialContext().lookup(RESOUCE_JDBC_PREFIX + name);
+		return initialContext().lookup(RESOURCE_JDBC_PREFIX + name);
+	}
+
+	public static Object resource_node(String name) throws Exception {
+		return initialContext().lookup(RESOURCE_NODE_PREFIX + name);
 	}
 
 	@SuppressWarnings("unchecked")
-	public static ConcurrentHashMap<String, Object> resource_node() throws Exception {
-		return (ConcurrentHashMap<String, Object>) initialContext().lookup(RESOUCE_NODE);
+	public static LinkedBlockingQueue<JsonElement> resource_node_eventQueue() throws Exception {
+		return (LinkedBlockingQueue<JsonElement>) initialContext().lookup(RESOURCE_NODE_EVENTQUEUE);
+	}
+
+	public static synchronized JsonElement resource_node_applications() throws Exception {
+		Object o = initialContext().lookup(RESOURCE_NODE_APPLICATIONS);
+		if (null != o) {
+			return (JsonElement) o;
+		}
+		return null;
+	}
+
+	public static synchronized void resource_node_applications(JsonElement jsonElement) throws Exception {
+		initialContext().rebind(RESOURCE_NODE_APPLICATIONS, jsonElement);
+	}
+
+	public static synchronized Date resource_node_applicationsTimestamp() throws Exception {
+		Object o = initialContext().lookup(RESOURCE_NODE_APPLICATIONSTIMESTAMP);
+		if (null != o) {
+			return (Date) o;
+		}
+		return null;
+	}
+
+	public static synchronized void resource_node_applicationsTimestamp(Date date) throws Exception {
+		initialContext().rebind(RESOURCE_NODE_APPLICATIONSTIMESTAMP, date);
 	}
 
-	public static void registWebServer() {
+	public static synchronized String resource_node_centersPirmaryNode() throws Exception {
+		Object o = initialContext().lookup(RESOURCE_NODE_CENTERSPRIMARYNODE);
+		if (null != o) {
+			return (String) o;
+		}
+		return null;
+	}
+
+	public static synchronized void resource_node_centersPirmaryNode(String node) throws Exception {
+		initialContext().rebind(RESOURCE_NODE_CENTERSPRIMARYNODE, node);
+	}
+
+	public static synchronized Integer resource_node_centersPirmaryPort() throws Exception {
+		Object o = initialContext().lookup(RESOURCE_NODE_CENTERSPRIMARYPORT);
+		if (null != o) {
+			return (Integer) o;
+		}
+		return null;
+	}
+
+	public static synchronized void resource_node_centersPirmaryPort(Integer port) throws Exception {
+		initialContext().rebind(RESOURCE_NODE_CENTERSPRIMARYPORT, port);
+	}
+
+	public static synchronized Boolean resource_node_centersPirmarySslEnable() throws Exception {
+		Object o = initialContext().lookup(RESOURCE_NODE_CENTERSPRIMARYSSLENABLE);
+		if (null != o) {
+			return (Boolean) o;
+		}
+		return null;
+	}
 
+	public static synchronized void resource_node_centersPirmarySslEnable(Boolean sslEnable) throws Exception {
+		initialContext().rebind(RESOURCE_NODE_CENTERSPRIMARYSSLENABLE, sslEnable);
 	}
 
 }

+ 23 - 35
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/CreateSample.java

@@ -10,7 +10,6 @@ import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import org.apache.commons.beanutils.MethodUtils;
 import org.apache.commons.io.FileUtils;
@@ -19,6 +18,8 @@ import org.apache.commons.lang3.reflect.FieldUtils;
 import org.junit.Test;
 
 import com.google.gson.JsonElement;
+import com.x.base.core.entity.StorageProtocol;
+import com.x.base.core.entity.StorageType;
 import com.x.base.core.project.annotation.FieldDescribe;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.logger.Logger;
@@ -52,6 +53,7 @@ public class CreateSample {
 		classes.add(WorkTime.class);
 		classes.add(ZhengwuDingding.class);
 		classes.add(ExternalDataSource.class);
+		classes.add(ExternalStorageSource.class);
 
 		Collections.sort(classes, new Comparator<Class<?>>() {
 			public int compare(Class<?> c1, Class<?> c2) {
@@ -70,6 +72,7 @@ public class CreateSample {
 			FileUtils.write(file, XGsonBuilder.toJson(map), DefaultCharset.charset);
 		}
 		this.convertExternalDataSource2ExternalDataSources();
+		this.convertExternalStorageSource2ExternalStorageSources();
 		this.renameNode();
 
 	}
@@ -79,14 +82,31 @@ public class CreateSample {
 				"configSample/externalDataSource.json");
 		File file_externalDataSources = new File(FileTools.parent(FileTools.parent(new File("./"))),
 				"configSample/externalDataSources.json");
-		JsonElement jsonElement = XGsonBuilder.instance().fromJson(FileUtils.readFileToString(file_externalDataSource),
-				JsonElement.class);
+		JsonElement jsonElement = XGsonBuilder.instance()
+				.fromJson(FileUtils.readFileToString(file_externalDataSource, "utf-8"), JsonElement.class);
 		List<JsonElement> list = new ArrayList<>();
 		list.add(jsonElement);
 		FileUtils.writeStringToFile(file_externalDataSources, XGsonBuilder.toJson(list), DefaultCharset.charset);
 		file_externalDataSource.delete();
 	}
 
+	private void convertExternalStorageSource2ExternalStorageSources() throws Exception, IOException {
+		File file_externalStorageSource = new File(FileTools.parent(FileTools.parent(new File("./"))),
+				"configSample/externalStorageSource.json");
+		File file_externalStorageSources = new File(FileTools.parent(FileTools.parent(new File("./"))),
+				"configSample/externalStorageSources.json");
+		JsonElement jsonElement = XGsonBuilder.instance()
+				.fromJson(FileUtils.readFileToString(file_externalStorageSource, "utf-8"), JsonElement.class);
+		List<JsonElement> list = new ArrayList<>();
+		list.add(jsonElement);
+		LinkedHashMap<String, List<JsonElement>> map = new LinkedHashMap<>();
+		for (StorageType o : StorageType.values()) {
+			map.put(o.toString(), list);
+		}
+		FileUtils.writeStringToFile(file_externalStorageSources, XGsonBuilder.toJson(map), DefaultCharset.charset);
+		file_externalStorageSource.delete();
+	}
+
 	private void renameNode() throws Exception, IOException {
 		File file_node = new File(FileTools.parent(FileTools.parent(new File("./"))), "configSample/node.json");
 		File file_node_local = new File(FileTools.parent(FileTools.parent(new File("./"))),
@@ -119,39 +139,7 @@ public class CreateSample {
 				}
 			}
 		}
-		// EntryComparator entryComparator = new EntryComparator();
-		// map = map.entrySet().stream().sorted(entryComparator)
-		// .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v1,
-		// LinkedHashMap::new));
 		return map;
 	}
 
-	public static class EntryComparator implements Comparator<Entry<String, Object>> {
-		public int compare(Entry<String, Object> en1, Entry<String, Object> en2) {
-			String k1 = en1.getKey();
-			String k2 = en2.getKey();
-			return 1;
-			// if ((!k1.startsWith("###")) && (!k2.startsWith("###"))) {
-			// return 1;
-			// } else {
-			// if (k1.startsWith("###")) {
-			// k1 = StringUtils.substringAfter(k1, "###");
-			// }
-			// if (k2.startsWith("###")) {
-			// k2 = StringUtils.substringAfter(k2, "###");
-			// }
-			// if (StringUtils.equals(k1, k2)) {
-			// if (en1.getKey().startsWith("###")) {
-			// return -1;
-			// }
-			// if (en2.getKey().startsWith("###")) {
-			// return 1;
-			// }
-			// }
-			// return k1.compareTo(k2);
-			// }
-
-		}
-	}
-
 }

+ 0 - 188
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataMapping.java

@@ -1,188 +0,0 @@
-//package com.x.base.core.project.config;
-//
-//import com.x.base.core.container.LogLevel;
-//import com.x.base.core.project.gson.GsonPropertyObject;
-//
-//public class DataMapping extends GsonPropertyObject {
-//
-////	name		配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。详情-点此处。
-////	url		连接数据库的url,不同数据库不一样。例如:
-////	mysql : jdbc:mysql://10.20.153.104:3306/druid2
-////	oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
-////	username		连接数据库的用户名
-////	password		连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里
-////	driverClassName	根据url自动识别	这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
-////	initialSize	0	初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
-////	maxActive	8	最大连接池数量
-////	maxIdle	8	已经不再使用,配置了也没效果
-////	minIdle		最小连接池数量
-////	maxWait		获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
-////	poolPreparedStatements	false	是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
-////	maxPoolPreparedStatementPerConnectionSize	-1	要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
-////	validationQuery		用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
-////	validationQueryTimeout		单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
-////	testOnBorrow	true	申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
-////	testOnReturn	false	归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
-////	testWhileIdle	false	建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
-////	keepAlive	false
-////	(1.0.28)	连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。
-////	timeBetweenEvictionRunsMillis	1分钟(1.0.14)	有两个含义:
-////	1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
-////	2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
-////	numTestsPerEvictionRun	30分钟(1.0.14)	不再使用,一个DruidDataSource只支持一个EvictionRun
-////	minEvictableIdleTimeMillis		连接保持空闲而不被驱逐的最小时间
-////	connectionInitSqls		物理连接初始化的时候执行的sql
-////	exceptionSorter	根据dbType自动识别	当数据库抛出一些不可恢复的异常时,抛弃连接
-////	filters		属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
-////	监控统计用的filter:stat
-////	日志用的filter:log4j
-////	防御sql注入的filter:wall
-////	proxyFilters		类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系
-//
-//	private String name;
-//	private String url;
-//	private String username;
-//	private String password;
-//	private String driverClassName;
-//	private Integer initialSize;
-//	private Integer maxActive;
-//	private Integer minIdle; // 最小连接池数量
-//
-//	private LogLevel toolLevel = LogLevel.WARN;
-//	private LogLevel runtimeLevel = LogLevel.WARN;
-//	private LogLevel dataCacheLevel = LogLevel.WARN;
-//	private LogLevel metaDataLevel = LogLevel.WARN;
-//	private LogLevel enhanceLevel = LogLevel.WARN;
-//	private LogLevel queryLevel = LogLevel.WARN;
-//	private LogLevel sqlLevel = LogLevel.WARN;
-//	private LogLevel jdbcLevel = LogLevel.ERROR;
-//
-//	public String getName() {
-//		return name;
-//	}
-//
-//	public String getDriverClassName() {
-//		return driverClassName;
-//	}
-//
-//	public Integer getInitialSize() {
-//		return initialSize;
-//	}
-//
-//	public Integer getMaxActive() {
-//		return maxActive;
-//	}
-//
-//	public Integer getMinIdle() {
-//		return minIdle;
-//	}
-//
-//	public String getUrl() {
-//		return url;
-//	}
-//
-//	public void setUrl(String url) {
-//		this.url = url;
-//	}
-//
-//	public String getUsername() {
-//		return username;
-//	}
-//
-//	public void setUsername(String username) {
-//		this.username = username;
-//	}
-//
-//	public String getPassword() {
-//		return password;
-//	}
-//
-//	public void setPassword(String password) {
-//		this.password = password;
-//	}
-//
-//	public LogLevel getToolLevel() {
-//		return toolLevel;
-//	}
-//
-//	public void setToolLevel(LogLevel toolLevel) {
-//		this.toolLevel = toolLevel;
-//	}
-//
-//	public LogLevel getRuntimeLevel() {
-//		return runtimeLevel;
-//	}
-//
-//	public void setRuntimeLevel(LogLevel runtimeLevel) {
-//		this.runtimeLevel = runtimeLevel;
-//	}
-//
-//	public LogLevel getDataCacheLevel() {
-//		return dataCacheLevel;
-//	}
-//
-//	public void setDataCacheLevel(LogLevel dataCacheLevel) {
-//		this.dataCacheLevel = dataCacheLevel;
-//	}
-//
-//	public LogLevel getMetaDataLevel() {
-//		return metaDataLevel;
-//	}
-//
-//	public void setMetaDataLevel(LogLevel metaDataLevel) {
-//		this.metaDataLevel = metaDataLevel;
-//	}
-//
-//	public LogLevel getEnhanceLevel() {
-//		return enhanceLevel;
-//	}
-//
-//	public void setEnhanceLevel(LogLevel enhanceLevel) {
-//		this.enhanceLevel = enhanceLevel;
-//	}
-//
-//	public LogLevel getQueryLevel() {
-//		return queryLevel;
-//	}
-//
-//	public void setQueryLevel(LogLevel queryLevel) {
-//		this.queryLevel = queryLevel;
-//	}
-//
-//	public LogLevel getSqlLevel() {
-//		return sqlLevel;
-//	}
-//
-//	public void setSqlLevel(LogLevel sqlLevel) {
-//		this.sqlLevel = sqlLevel;
-//	}
-//
-//	public LogLevel getJdbcLevel() {
-//		return jdbcLevel;
-//	}
-//
-//	public void setJdbcLevel(LogLevel jdbcLevel) {
-//		this.jdbcLevel = jdbcLevel;
-//	}
-//
-//	public void setName(String name) {
-//		this.name = name;
-//	}
-//
-//	public void setDriverClassName(String driverClassName) {
-//		this.driverClassName = driverClassName;
-//	}
-//
-//	public void setInitialSize(Integer initialSize) {
-//		this.initialSize = initialSize;
-//	}
-//
-//	public void setMaxActive(Integer maxActive) {
-//		this.maxActive = maxActive;
-//	}
-//
-//	public void setMinIdle(Integer minIdle) {
-//		this.minIdle = minIdle;
-//	}
-//
-//}

+ 0 - 14
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/DataMappings.java

@@ -1,14 +0,0 @@
-//package com.x.base.core.project.config;
-//
-//import java.util.concurrent.ConcurrentHashMap;
-//import java.util.concurrent.CopyOnWriteArrayList;
-//
-//public class DataMappings extends ConcurrentHashMap<String, CopyOnWriteArrayList<DataMapping>> {
-//
-//	private static final long serialVersionUID = -2013392322121523454L;
-//
-//	public DataMappings() {
-//		super();
-//	}
-//
-//}

+ 101 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ExternalStorageSource.java

@@ -0,0 +1,101 @@
+package com.x.base.core.project.config;
+
+import org.apache.commons.lang3.BooleanUtils;
+
+import com.x.base.core.entity.StorageProtocol;
+import com.x.base.core.project.annotation.FieldDescribe;
+
+public class ExternalStorageSource extends ConfigObject {
+
+	public ExternalStorageSource() {
+		this.protocol = default_protocol;
+		this.username = default_username;
+		this.password = default_password;
+		this.host = default_host;
+		this.port = default_port;
+		this.prefix = default_prefix;
+		this.enable = default_enable;
+		this.weight = default_weight;
+		this.name = default_name;
+		this.deepPath = default_deepPath;
+
+	}
+
+	public static ExternalStorageSource defaultInstance() {
+		return new ExternalStorageSource();
+
+	}
+
+	public static final StorageProtocol default_protocol = StorageProtocol.webdav;
+	public static final String default_username = "admin";
+	public static final String default_password = "admin";
+	public static final String default_host = "127.0.0.1";
+	public static final Integer default_port = 8080;
+	public static final String default_prefix = "";
+	public static final Integer default_weight = 100;
+	public static final Boolean default_enable = true;
+	public static final String default_name = "251";
+	public static final Boolean default_deepPath = false;
+
+	@FieldDescribe("协议,可选值ftp,webdav")
+	private StorageProtocol protocol;
+	@FieldDescribe("登录用户名.")
+	private String username;
+	@FieldDescribe("登录密码.")
+	private String password;
+	@FieldDescribe("主机地址.")
+	private String host;
+	@FieldDescribe("端口.")
+	private Integer port;
+	@FieldDescribe("前缀路径.")
+	private String prefix;
+	@FieldDescribe("是否启用")
+	private Boolean enable;
+	@FieldDescribe("设置权重.")
+	private Integer weight;
+	@FieldDescribe("存储节点名,对应存储名称,谨慎修改.")
+	private String name;
+	@FieldDescribe("是否使用更深的路径.")
+	private Boolean deepPath;
+
+	public StorageProtocol getProtocol() {
+		return protocol;
+	}
+
+	public String getUsername() {
+		return username;
+	}
+
+	public String getPassword() {
+		return password;
+	}
+
+	public String getHost() {
+		return host;
+	}
+
+	public Integer getPort() {
+		return port;
+	}
+
+	public String getPrefix() {
+		return prefix;
+	}
+
+	public Boolean getEnable() {
+		return BooleanUtils.isTrue(this.enable);
+	}
+
+	public Integer getWeight() {
+		return weight;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Boolean getDeepPath() {
+		return BooleanUtils.isTrue(this.deepPath);
+	}
+
+}

+ 23 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ExternalStorageSources.java

@@ -0,0 +1,23 @@
+package com.x.base.core.project.config;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import com.x.base.core.entity.StorageType;
+
+public class ExternalStorageSources extends ConcurrentHashMap<StorageType, CopyOnWriteArrayList<ExternalStorageSource>> {
+
+	private static final long serialVersionUID = 8229115124625865737L;
+
+	public static ExternalStorageSources defaultInstance() {
+
+		ExternalStorageSources externalStorages = new ExternalStorageSources();
+
+		return externalStorages;
+	}
+
+	public ExternalStorageSources() {
+		super();
+	}
+
+}

+ 30 - 30
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/LogLevel.java

@@ -107,122 +107,122 @@ public class LogLevel extends ConfigObject {
 	}
 
 	public String x_attendance_assemble_control() {
-		return this.get(this.x_attendance_assemble_control);
+		return this.getLevel(this.x_attendance_assemble_control);
 	}
 
 	public String x_collaboration_core_message() {
-		return this.get(this.x_collaboration_core_message);
+		return this.getLevel(this.x_collaboration_core_message);
 	}
 
 	public String x_organization_core_express() {
-		return this.get(this.x_organization_core_express);
+		return this.getLevel(this.x_organization_core_express);
 	}
 
 	public String x_query_core_express() {
-		return this.get(this.x_query_core_express);
+		return this.getLevel(this.x_query_core_express);
 	}
 
 	public String x_bbs_assemble_control() {
-		return this.get(this.x_bbs_assemble_control);
+		return this.getLevel(this.x_bbs_assemble_control);
 	}
 
 	public String x_calendar_assemble_control() {
-		return this.get(this.x_calendar_assemble_control);
+		return this.getLevel(this.x_calendar_assemble_control);
 	}
 
 	public String x_cms_assemble_control() {
-		return this.get(this.x_cms_assemble_control);
+		return this.getLevel(this.x_cms_assemble_control);
 	}
 
 	public String x_component_assemble_control() {
-		return this.get(this.x_component_assemble_control);
+		return this.getLevel(this.x_component_assemble_control);
 	}
 
 	public String x_hotpic_assemble_control() {
-		return this.get(this.x_hotpic_assemble_control);
+		return this.getLevel(this.x_hotpic_assemble_control);
 	}
 
 	public String x_message_assemble_communicate() {
-		return this.get(this.x_message_assemble_communicate);
+		return this.getLevel(this.x_message_assemble_communicate);
 	}
 
 	public String x_mind_assemble_control() {
-		return this.get(this.x_mind_assemble_control);
+		return this.getLevel(this.x_mind_assemble_control);
 	}
 
 	public String x_okr_assemble_control() {
-		return this.get(this.x_okr_assemble_control);
+		return this.getLevel(this.x_okr_assemble_control);
 	}
 
 	public String x_organization_assemble_express() {
-		return this.get(this.x_organization_assemble_express);
+		return this.getLevel(this.x_organization_assemble_express);
 	}
 
 	public String x_organization_assemble_personal() {
-		return this.get(this.x_organization_assemble_personal);
+		return this.getLevel(this.x_organization_assemble_personal);
 	}
 
 	public String x_portal_assemble_designer() {
-		return this.get(this.x_portal_assemble_designer);
+		return this.getLevel(this.x_portal_assemble_designer);
 	}
 
 	public String x_portal_assemble_surface() {
-		return this.get(this.x_portal_assemble_surface);
+		return this.getLevel(this.x_portal_assemble_surface);
 	}
 
 	public String x_processplatform_assemble_bam() {
-		return this.get(this.x_processplatform_assemble_bam);
+		return this.getLevel(this.x_processplatform_assemble_bam);
 	}
 
 	public String x_program_center() {
-		return this.get(this.x_program_center);
+		return this.getLevel(this.x_program_center);
 	}
 
 	public String x_processplatform_service_processing() {
-		return this.get(this.x_processplatform_service_processing);
+		return this.getLevel(this.x_processplatform_service_processing);
 	}
 
 	public String x_processplatform_assemble_surface() {
-		return this.get(this.x_processplatform_assemble_surface);
+		return this.getLevel(this.x_processplatform_assemble_surface);
 	}
 
 	public String x_processplatform_assemble_designer() {
-		return this.get(this.x_processplatform_assemble_designer);
+		return this.getLevel(this.x_processplatform_assemble_designer);
 	}
 
 	public String x_query_assemble_surface() {
-		return this.get(this.x_query_assemble_surface);
+		return this.getLevel(this.x_query_assemble_surface);
 	}
 
 	public String x_query_assemble_designer() {
-		return this.get(this.x_query_assemble_designer);
+		return this.getLevel(this.x_query_assemble_designer);
 	}
 
 	public String x_query_service_processing() {
-		return this.get(this.x_query_service_processing);
+		return this.getLevel(this.x_query_service_processing);
 	}
 
 	public String x_meeting_assemble_control() {
-		return this.get(this.x_meeting_assemble_control);
+		return this.getLevel(this.x_meeting_assemble_control);
 	}
 
 	public String x_organization_assemble_authentication() {
-		return this.get(this.x_organization_assemble_authentication);
+		return this.getLevel(this.x_organization_assemble_authentication);
 	}
 
 	public String x_organization_assemble_control() {
-		return this.get(this.x_organization_assemble_control);
+		return this.getLevel(this.x_organization_assemble_control);
 	}
 
 	public String x_general_assemble_control() {
-		return this.get(this.x_general_assemble_control);
+		return this.getLevel(this.x_general_assemble_control);
 	}
 
 	public String x_file_assemble_control() {
-		return this.get(this.x_general_assemble_control);
+		return this.getLevel(this.x_general_assemble_control);
 	}
 
-	private String get(String str) {
+	private String getLevel(String str) {
 		if (StringUtils.equalsIgnoreCase(str, Logger.ERROR)) {
 			return Logger.ERROR;
 		}

+ 34 - 48
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Node.java

@@ -4,6 +4,7 @@ import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.tools.BaseTools;
 import com.x.base.core.project.tools.DateTools;
 
 public class Node extends ConfigObject {
@@ -16,6 +17,7 @@ public class Node extends ConfigObject {
 		Node o = new Node();
 		o.enable = true;
 		o.isPrimaryCenter = true;
+		o.center = CenterServer.defaultInstance();
 		o.application = ApplicationServer.defaultInstance();
 		o.web = WebServer.defaultInstance();
 		o.data = DataServer.defaultInstance();
@@ -36,6 +38,8 @@ public class Node extends ConfigObject {
 	private Boolean enable;
 	@FieldDescribe("是否是center节点,仅允许存在一个center节点")
 	private Boolean isPrimaryCenter;
+	@FieldDescribe("Center服务器配置")
+	private CenterServer center;
 	@FieldDescribe("Application服务器配置")
 	private ApplicationServer application;
 	@FieldDescribe("Web服务器配置")
@@ -71,10 +75,40 @@ public class Node extends ConfigObject {
 	@FieldDescribe("是否自动启动")
 	private Boolean autoStart;
 
+	/* 20191009兼容centerServer */
+	protected void setCenter(CenterServer centerServer) {
+		this.center = centerServer;
+	}
+	/* 20191009兼容centerServer end */
+
 	public Boolean autoStart() {
 		return BooleanUtils.isTrue(autoStart);
 	}
 
+	public Boolean getEnable() {
+		return BooleanUtils.isTrue(this.enable);
+	}
+
+	public CenterServer getCenter() {
+		return (center == null) ? CenterServer.defaultInstance() : this.center;
+	}
+
+	public ApplicationServer getApplication() {
+		return (application == null) ? ApplicationServer.defaultInstance() : this.application;
+	}
+
+	public WebServer getWeb() {
+		return (web == null) ? WebServer.defaultInstance() : this.web;
+	}
+
+	public DataServer getData() {
+		return (data == null) ? DataServer.defaultInstance() : this.data;
+	}
+
+	public StorageServer getStorage() {
+		return (storage == null) ? StorageServer.defaultInstance() : this.storage;
+	}
+
 	public String getLogLevel() {
 		// "trace", "debug", "info", "warn", "error" or "off"
 		if (StringUtils.equals("trace", this.logLevel)) {
@@ -144,54 +178,6 @@ public class Node extends ConfigObject {
 		return (restoreStorage == null) ? new ScheduleRestoreStorage() : this.restoreStorage;
 	}
 
-	public void setIsPrimaryCenter(Boolean isPrimaryCenter) {
-		this.isPrimaryCenter = isPrimaryCenter;
-	}
-
-	public Boolean getEnable() {
-		return enable;
-	}
-
-	public void setEnable(Boolean enable) {
-		this.enable = enable;
-	}
-
-	public ApplicationServer getApplication() {
-		return application;
-	}
-
-	public void setApplication(ApplicationServer application) {
-		this.application = application;
-	}
-
-	public WebServer getWeb() {
-		return web;
-	}
-
-	public void setWeb(WebServer web) {
-		this.web = web;
-	}
-
-	public DataServer getData() {
-		return data;
-	}
-
-	public void setData(DataServer data) {
-		this.data = data;
-	}
-
-	public StorageServer getStorage() {
-		return storage;
-	}
-
-	public void setStorage(StorageServer storage) {
-		this.storage = storage;
-	}
-
-	public void setLogLevel(String logLevel) {
-		this.logLevel = logLevel;
-	}
-
 	public static class ScheduleDumpData extends ConfigObject {
 
 		public static ScheduleDumpData defaultInstance() {

+ 13 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/Nodes.java

@@ -17,6 +17,19 @@ public class Nodes extends ConcurrentSkipListMap<String, Node> {
 		super();
 	}
 
+	private CenterServers centerServers;
+
+	public CenterServers centerServers() throws Exception {
+		if (centerServers == null) {
+			synchronized (Nodes.class) {
+				if (centerServers == null) {
+					centerServers = new CenterServers(this);
+				}
+			}
+		}
+		return centerServers;
+	}
+
 	private ApplicationServers applicationServers;
 
 	public ApplicationServers applicationServers() throws Exception {

+ 76 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/ProcessPlatform.java

@@ -13,6 +13,21 @@ import com.x.base.core.project.tools.DefaultCharset;
 
 public class ProcessPlatform extends ConfigObject {
 
+	public final static Integer DEFAULT_FORMVERSIONPERIOD = 45;
+	public final static Integer DEFAULT_PROCESSVERSIONPERIOD = 45;
+	public final static Integer DEFAULT_SCRIPTVERSIONPERIOD = 45;
+
+	public final static String DEFAULT_DOCTOWORDTYPE = "local";
+
+	public final static String DOCTOWORDTYPE_LOCAL = "local";
+	public final static String DOCTOWORDTYPE_CLOUD = "cloud";
+
+	public final static String DEFAULT_DOCTOWORDDEFAULTFILENAME = "正文.docx";
+
+	public final static String DEFAULT_DOCTOWORDDEFAULTSITE = "$doc";
+
+	public final static Boolean DEFAULT_PROCESSINGTASKSAMEJOBACTIVITYIDENTITY = true;
+
 	public static ProcessPlatform defaultInstance() {
 		return new ProcessPlatform();
 	}
@@ -24,6 +39,13 @@ public class ProcessPlatform extends ConfigObject {
 		this.reorganize = new Reorganize();
 		this.dataMerge = new DataMerge();
 		this.maintenanceIdentity = "";
+		this.formVersionPeriod = DEFAULT_FORMVERSIONPERIOD;
+		this.processVersionPeriod = DEFAULT_PROCESSVERSIONPERIOD;
+		this.scriptVersionPeriod = DEFAULT_SCRIPTVERSIONPERIOD;
+		this.docToWordType = DEFAULT_DOCTOWORDTYPE;
+		this.docToWordDefaultFileName = DEFAULT_DOCTOWORDDEFAULTFILENAME;
+		this.docToWordDefaultSite = DEFAULT_DOCTOWORDDEFAULTSITE;
+		this.processingTaskSameJobActivityIdentity = DEFAULT_PROCESSINGTASKSAMEJOBACTIVITYIDENTITY;
 	}
 
 	@FieldDescribe("提醒设置,设置提醒间隔.")
@@ -47,6 +69,60 @@ public class ProcessPlatform extends ConfigObject {
 	@FieldDescribe("维护身份,当工作发生意外错误,无法找到对应的处理人情况下,先尝试将工作分配给创建身份,如果创建身份也不可获取,那么分配给指定人员,默认情况下这个值为空.")
 	private String maintenanceIdentity;
 
+	@FieldDescribe("表单历史版本保留天数.")
+	private Integer formVersionPeriod;
+
+	@FieldDescribe("流程历史版本保留天数.")
+	private Integer processVersionPeriod;
+
+	@FieldDescribe("脚本历史版本保留天数.")
+	private Integer scriptVersionPeriod;
+
+	@FieldDescribe("HTML版式公文转换成Word文件方式,local,cloud.")
+	private String docToWordType;
+
+	@FieldDescribe("HTML版式公文转换成Word文件缺省文件名.")
+	private String docToWordDefaultFileName;
+
+	@FieldDescribe("HTML版式公文转换成Word文件缺省site.")
+	private String docToWordDefaultSite;
+
+	@FieldDescribe("同步处理同一工作在同一环节同一处理身份.")
+	private Boolean processingTaskSameJobActivityIdentity;
+
+	public Boolean getProcessingTaskSameJobActivityIdentity() {
+		return processingTaskSameJobActivityIdentity == null ? DEFAULT_PROCESSINGTASKSAMEJOBACTIVITYIDENTITY
+				: BooleanUtils.isTrue(this.processingTaskSameJobActivityIdentity);
+	}
+
+	public Integer getFormVersionPeriod() {
+		return (formVersionPeriod == null || formVersionPeriod < 1) ? DEFAULT_FORMVERSIONPERIOD
+				: this.formVersionPeriod;
+	}
+
+	public Integer getProcessVersionPeriod() {
+		return (processVersionPeriod == null || processVersionPeriod < 1) ? DEFAULT_PROCESSVERSIONPERIOD
+				: this.processVersionPeriod;
+	}
+
+	public Integer getScriptVersionPeriod() {
+		return (scriptVersionPeriod == null || scriptVersionPeriod < 1) ? DEFAULT_SCRIPTVERSIONPERIOD
+				: this.scriptVersionPeriod;
+	}
+
+	public String getDocToWordType() {
+		return StringUtils.isEmpty(docToWordType) ? DEFAULT_DOCTOWORDTYPE : docToWordType;
+	}
+
+	public String getDocToWordDefaultFileName() {
+		return StringUtils.isEmpty(docToWordDefaultFileName) ? DEFAULT_DOCTOWORDDEFAULTFILENAME
+				: docToWordDefaultFileName;
+	}
+
+	public String getDocToWordDefaultSite() {
+		return StringUtils.isEmpty(docToWordDefaultSite) ? DEFAULT_DOCTOWORDDEFAULTSITE : docToWordDefaultSite;
+	}
+
 	public Press getPress() {
 		return this.press == null ? new Press() : this.press;
 	}

+ 54 - 32
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageMapping.java

@@ -10,54 +10,68 @@ public class StorageMapping extends GsonPropertyObject {
 	private String password;
 	private String host;
 	private Integer port;
-
-	private Boolean enable;
+	private String prefix;
 	private Integer weight;
-	/* 关联到storageServer的name */
 	private String name;
+	private Boolean deepPath;
+
+	public StorageMapping() {
+
+	}
+
+	public StorageMapping(ExternalStorageSource source) {
+		this.protocol = source.getProtocol();
+		this.username = source.getUsername();
+		this.password = source.getPassword();
+		this.host = source.getHost();
+		this.port = source.getPort();
+		this.prefix = source.getPrefix();
+		this.weight = source.getWeight();
+		this.name = source.getName();
+		this.deepPath = source.getDeepPath();
+
+	}
+
+	public StorageProtocol getProtocol() {
+		return protocol;
+	}
+
+	public String getUsername() {
+		return username;
+	}
 
 	public String getPassword() {
-		// return StringUtils.isEmpty(this.password) ? "" :
-		// UriParser.encode(this.password);
-		return this.password;
+		return password;
 	}
 
-	public Boolean getEnable() {
-		return enable;
+	public String getHost() {
+		return host;
 	}
 
-	public void setEnable(Boolean enable) {
-		this.enable = enable;
+	public Integer getPort() {
+		return port;
 	}
 
-	public Integer getWeight() {
-		return weight;
+	public String getPrefix() {
+		return prefix;
 	}
 
-	public void setWeight(Integer weight) {
-		this.weight = weight;
+	public Integer getWeight() {
+		return weight;
 	}
 
 	public String getName() {
 		return name;
 	}
 
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public StorageProtocol getProtocol() {
-		return protocol;
+	public Boolean getDeepPath() {
+		return deepPath;
 	}
 
 	public void setProtocol(StorageProtocol protocol) {
 		this.protocol = protocol;
 	}
 
-	public String getUsername() {
-		return username;
-	}
-
 	public void setUsername(String username) {
 		this.username = username;
 	}
@@ -66,20 +80,28 @@ public class StorageMapping extends GsonPropertyObject {
 		this.password = password;
 	}
 
-	public String getHost() {
-		return host;
-	}
-
 	public void setHost(String host) {
 		this.host = host;
 	}
 
-	public Integer getPort() {
-		return port;
-	}
-
 	public void setPort(Integer port) {
 		this.port = port;
 	}
 
+	public void setPrefix(String prefix) {
+		this.prefix = prefix;
+	}
+
+	public void setWeight(Integer weight) {
+		this.weight = weight;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setDeepPath(Boolean deepPath) {
+		this.deepPath = deepPath;
+	}
+
 }

+ 21 - 17
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageMappings.java

@@ -1,11 +1,10 @@
 package com.x.base.core.project.config;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Random;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 
 import com.x.base.core.entity.Storage;
@@ -22,6 +21,20 @@ public class StorageMappings extends ConcurrentHashMap<StorageType, CopyOnWriteA
 		super();
 	}
 
+	public StorageMappings(ExternalStorageSources externalStorageSources) {
+		for (Entry<StorageType, CopyOnWriteArrayList<ExternalStorageSource>> entry : externalStorageSources
+				.entrySet()) {
+			CopyOnWriteArrayList<StorageMapping> list = new CopyOnWriteArrayList<>();
+			for (ExternalStorageSource externalStorageSource : entry.getValue()) {
+				if (BooleanUtils.isTrue(externalStorageSource.getEnable())) {
+					StorageMapping storageMapping = new StorageMapping(externalStorageSource);
+					list.add(storageMapping);
+				}
+				this.put(entry.getKey(), list);
+			}
+		}
+	}
+
 	public StorageMappings(Nodes nodeConfigs) throws Exception {
 		super();
 		/** 填充空值 */
@@ -34,15 +47,15 @@ public class StorageMappings extends ConcurrentHashMap<StorageType, CopyOnWriteA
 			StorageServer server = en.getValue();
 			for (Account account : server.getCalculatedAccounts()) {
 				StorageMapping o = new StorageMapping();
-				o.setEnable(true);
 				o.setHost(node);
+				o.setDeepPath(server.getDeepPath());
+				o.setPrefix(server.getPrefix());
+				o.setName(server.getName());
 				o.setPassword(account.getPassword());
-				// o.setName(account.getName());
 				o.setPort(en.getValue().getPort());
 				o.setUsername(account.getUsername());
 				o.setProtocol(account.getProtocol());
-				o.setWeight((account.getWeight() == null) ? 100 : account.getWeight());
-				o.setName(server.getName());
+				o.setWeight(account.getWeight());
 				StorageType type = StorageType.valueOf(account.getUsername());
 				this.get(type).add(o);
 			}
@@ -91,23 +104,14 @@ public class StorageMappings extends ConcurrentHashMap<StorageType, CopyOnWriteA
 		if (ListTools.isEmpty(list)) {
 			throw new Exception("can not get storage of " + type);
 		}
-		List<StorageMapping> availables = new ArrayList<>();
-		for (StorageMapping o : list) {
-			if (o.getEnable()) {
-				availables.add(o);
-			}
-		}
-		if (availables.isEmpty()) {
-			throw new Exception("storageType{:" + type + " has none available storage.");
-		}
 		int total = 0;
 		Random random = new Random();
-		for (StorageMapping o : availables) {
+		for (StorageMapping o : list) {
 			total += o.getWeight();
 		}
 		int rdm = random.nextInt(total);
 		int current = 0;
-		for (StorageMapping o : availables) {
+		for (StorageMapping o : list) {
 			current += o.getWeight();
 			if (rdm <= current) {
 				return o;

+ 17 - 3
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/StorageServer.java

@@ -8,15 +8,16 @@ import org.apache.commons.lang3.StringUtils;
 import com.x.base.core.entity.StorageProtocol;
 import com.x.base.core.entity.StorageType;
 import com.x.base.core.project.annotation.FieldDescribe;
-import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.tools.ListTools;
 
 public class StorageServer extends ConfigObject {
 
 	private static final Integer default_port = 20040;
 	private static final String default_passivePorts = "29000-30000";
-	/** 2的八次方最小的质数 */
+	private static final String default_prefix = "";
+	/** 2的八次方最大的质数 */
 	private static final String default_name = "251";
+	private static final Boolean default_deepPath = false;
 
 	public static StorageServer defaultInstance() {
 		return new StorageServer();
@@ -28,6 +29,8 @@ public class StorageServer extends ConfigObject {
 		this.sslEnable = false;
 		this.name = default_name;
 		this.accounts = new CopyOnWriteArrayList<Account>();
+		this.prefix = default_prefix;
+		this.deepPath = default_deepPath;
 	}
 
 	@FieldDescribe("是否启用,对于二进制流文件,比如附件,图片等存储在单独的文件服务器中,可以支持多种文件服务器,默认情况下使用ftp服务器作为文件服务器,每个节点可以启动一个文件服务器以提供高性能.")
@@ -42,6 +45,10 @@ public class StorageServer extends ConfigObject {
 	private CopyOnWriteArrayList<Account> accounts;
 	@FieldDescribe("ftp传输有主动和被动之分,如果使用了被动传输,设置被动端口范围,默认为29000-30000.")
 	private String passivePorts;
+	@FieldDescribe("路径前缀.")
+	private String prefix;
+	@FieldDescribe("使用更深的路径")
+	private Boolean deepPath;
 
 	public CopyOnWriteArrayList<Account> getCalculatedAccounts() throws Exception {
 		if (ListTools.isEmpty(accounts)) {
@@ -49,7 +56,6 @@ public class StorageServer extends ConfigObject {
 			for (StorageType o : StorageType.values()) {
 				Account account = new Account();
 				account.setProtocol(StorageProtocol.ftp);
-				// account.setName(o.toString());
 				account.setUsername(o.toString());
 				account.setWeight(100);
 				account.setPassword(Config.token().getPassword());
@@ -59,6 +65,14 @@ public class StorageServer extends ConfigObject {
 		return accounts;
 	}
 
+	public String getPrefix() {
+		return StringUtils.isBlank(this.prefix) ? default_prefix : this.prefix;
+	}
+
+	public Boolean getDeepPath() {
+		return BooleanUtils.isTrue(this.deepPath);
+	}
+
 	public String getPassivePorts() {
 		return StringUtils.isBlank(this.passivePorts) ? default_passivePorts : this.passivePorts;
 	}

+ 10 - 2
o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/WebServer.java

@@ -18,11 +18,13 @@ public class WebServer extends ConfigObject {
 		this.proxyHost = "";
 		this.proxyPort = null;
 		this.weight = default_weight;
+		this.dirAllowed = default_dirAllowed;
 	}
 
 	private static final Integer default_http_port = 80;
 	private static final Integer default_https_port = 443;
 	private static final Integer default_weight = 100;
+	private static final Boolean default_dirAllowed = false;
 
 	@FieldDescribe("是否启用")
 	private Boolean enable;
@@ -30,12 +32,18 @@ public class WebServer extends ConfigObject {
 	private Integer port;
 	@FieldDescribe("是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.")
 	private Boolean sslEnable;
-	@FieldDescribe("代理主机,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
+	@FieldDescribe("代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.")
 	private String proxyHost;
-	@FieldDescribe("代理端口,当服务器是通过apache/eginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
+	@FieldDescribe("代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.")
 	private Integer proxyPort;
 	@FieldDescribe("设置权重.当前没有作用,")
 	private Integer weight;
+	@FieldDescribe("允许浏览目录,")
+	private Boolean dirAllowed;
+
+	public Boolean getDirAllowed() {
+		return dirAllowed == null ? default_dirAllowed : dirAllowed;
+	}
 
 	public Integer getWeight() {
 		if (weight == null || weight < 0) {

+ 14 - 14
o2server/x_base_core_project/src/main/java/com/x/base/core/project/connection/ConnectionAction.java

@@ -25,22 +25,22 @@ import com.x.base.core.project.tools.ListTools;
 
 public class ConnectionAction {
 
-	private static String Access_Control_Allow_Credentials = "Access-Control-Allow-Credentials";
-	private static String Access_Control_Allow_Credentials_Value = "true";
-	private static String Access_Control_Allow_Headers = "Access-Control-Allow-Headers";
-	private static String Access_Control_Allow_Headers_Value = "x-requested-with, x-request, x-token,Content-Type, x-cipher, x-client";
-	private static String Access_Control_Allow_Methods = "Access-Control-Allow-Methods";
-	private static String Access_Control_Allow_Methods_Value = "GET, POST, OPTIONS, PUT, DELETE, HEAD, TRACE";
+	public static final String Access_Control_Allow_Credentials = "Access-Control-Allow-Credentials";
+	public static final String Access_Control_Allow_Credentials_Value = "true";
+	public static final String Access_Control_Allow_Headers = "Access-Control-Allow-Headers";
+	public static final String Access_Control_Allow_Headers_Value = "x-requested-with, x-request, x-token,Content-Type, x-cipher, x-client";
+	public static final String Access_Control_Allow_Methods = "Access-Control-Allow-Methods";
+	public static final String Access_Control_Allow_Methods_Value = "GET, POST, OPTIONS, PUT, DELETE, HEAD, TRACE";
 
-	private static String Cache_Control = "Cache-Control";
-	private static String Cache_Control_Value = "no-cache, no-transform";
-	private static String Content_Type = "Content-Type";
-	private static String Content_Type_Value = "application/json;charset=UTF-8";
+	public static final String Cache_Control = "Cache-Control";
+	public static final String Cache_Control_Value = "no-cache, no-transform";
+	public static final String Content_Type = "Content-Type";
+	public static final String Content_Type_Value = "application/json;charset=UTF-8";
 
-	private static String METHOD_PUT = "PUT";
-	private static String METHOD_POST = "POST";
-	private static String METHOD_GET = "GET";
-	private static String METHOD_DELETE = "DELETE";
+	public static final String METHOD_PUT = "PUT";
+	public static final String METHOD_POST = "POST";
+	public static final String METHOD_GET = "GET";
+	public static final String METHOD_DELETE = "DELETE";
 
 	private static Gson gson = XGsonBuilder.instance();
 

+ 10 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectConnectError.java

@@ -0,0 +1,10 @@
+package com.x.base.core.project.exception;
+
+public class ExceptionCollectConnectError extends PromptException {
+
+	private static final long serialVersionUID = 7551134321893884285L;
+
+	public ExceptionCollectConnectError() {
+		super("云服务器连接错误.");
+	}
+}

+ 10 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectDisable.java

@@ -0,0 +1,10 @@
+package com.x.base.core.project.exception;
+
+public class ExceptionCollectDisable extends PromptException {
+
+	private static final long serialVersionUID = 7551134321893884285L;
+
+	public ExceptionCollectDisable() {
+		super("禁用云服务.");
+	}
+}

+ 10 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionCollectValidateFailure.java

@@ -0,0 +1,10 @@
+package com.x.base.core.project.exception;
+
+public class ExceptionCollectValidateFailure extends PromptException {
+
+	private static final long serialVersionUID = 7551134321893884285L;
+
+	public ExceptionCollectValidateFailure() {
+		super("云服务器认证失败.");
+	}
+}

+ 13 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/exception/ExceptionUnsupportedMediaType.java

@@ -0,0 +1,13 @@
+package com.x.base.core.project.exception;
+
+import com.x.base.core.entity.JpaObject;
+
+public class ExceptionUnsupportedMediaType extends PromptException {
+
+	private static final long serialVersionUID = 1051687204485351261L;
+
+	public <T extends JpaObject> ExceptionUnsupportedMediaType(String type) {
+		super("不支持的文件类型:{}.",type);
+	}
+
+}

+ 4 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/gson/GsonPropertyObject.java

@@ -1,5 +1,7 @@
 package com.x.base.core.project.gson;
 
+import org.apache.commons.beanutils.PropertyUtils;
+
 import com.x.base.core.project.bean.PropertyObject;
 
 public abstract class GsonPropertyObject extends PropertyObject {
@@ -11,4 +13,6 @@ public abstract class GsonPropertyObject extends PropertyObject {
 		}
 		return null;
 	}
+
+	
 }

+ 3 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CaptchaFactory.java

@@ -1,6 +1,5 @@
 package com.x.base.core.project.instrument;
 
-import com.x.base.core.project.Applications;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.connection.CipherConnectionAction;
 import com.x.base.core.project.http.WrapOutBoolean;
@@ -14,8 +13,8 @@ public class CaptchaFactory {
 
 	public WoCaptcha create(Integer width, Integer height) throws Exception {
 		try {
-			String url = Config.x_program_centerUrlRoot() + Applications.joinQueryUri("captcha", "create", "width",
-					width.toString(), "height", height.toString());
+			String url = Config.url_x_program_center_jaxrs("captcha", "create", "width", width.toString(), "height",
+					height.toString());
 			Wo o = CipherConnectionAction.get(false, url).getData(Wo.class);
 			return o;
 		} catch (Exception e) {
@@ -29,8 +28,7 @@ public class CaptchaFactory {
 
 	public Boolean validate(String id, String answer) throws Exception {
 		try {
-			String url = Config.x_program_centerUrlRoot()
-					+ Applications.joinQueryUri("captcha", id, "validate", "answer", answer);
+			String url = Config.url_x_program_center_jaxrs("captcha", id, "validate", "answer", answer);
 			WrapOutBoolean wrap = CipherConnectionAction.get(false, url).getData(WrapOutBoolean.class);
 			return wrap.getValue();
 		} catch (Exception e) {

+ 4 - 7
o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CodeFactory.java

@@ -1,6 +1,5 @@
 package com.x.base.core.project.instrument;
 
-import com.x.base.core.project.Applications;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.connection.CipherConnectionAction;
 import com.x.base.core.project.http.WrapOutBoolean;
@@ -9,8 +8,7 @@ public class CodeFactory {
 
 	public void create(String mobile) throws Exception {
 		try {
-			String url = Config.x_program_centerUrlRoot()
-					+ Applications.joinQueryUri("code", "create", "mobile", mobile);
+			String url = Config.url_x_program_center_jaxrs("code", "create", "mobile", mobile);
 			CipherConnectionAction.get(false, url);
 		} catch (Exception e) {
 			throw new Exception("CodeFactory create error:" + mobile + ".", e);
@@ -19,8 +17,7 @@ public class CodeFactory {
 
 	public Boolean validate(String mobile, String answer) throws Exception {
 		try {
-			String url = Config.x_program_centerUrlRoot()
-					+ Applications.joinQueryUri("code", "validate", "mobile", mobile, "answer", answer);
+			String url = Config.url_x_program_center_jaxrs("code", "validate", "mobile", mobile, "answer", answer);
 			WrapOutBoolean wrap = CipherConnectionAction.get(false, url).getData(WrapOutBoolean.class);
 			return wrap.getValue();
 		} catch (Exception e) {
@@ -32,8 +29,8 @@ public class CodeFactory {
 		try {
 			Boolean value = this.validate(mobile, answer);
 			if (value == false) {
-				String url = Config.x_program_centerUrlRoot()
-						+ Applications.joinQueryUri("code", "validate", "mobile", mobile, "answer", answer, "cascade");
+				String url = Config.url_x_program_center_jaxrs("code", "validate", "mobile", mobile, "answer", answer,
+						"cascade");
 				WrapOutBoolean wrap = CipherConnectionAction.get(false, url).getData(WrapOutBoolean.class);
 				return wrap.getValue();
 			} else {

+ 1 - 2
o2server/x_base_core_project/src/main/java/com/x/base/core/project/instrument/CollectFactory.java

@@ -1,6 +1,5 @@
 package com.x.base.core.project.instrument;
 
-import com.x.base.core.project.Applications;
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.connection.CipherConnectionAction;
 
@@ -8,7 +7,7 @@ public class CollectFactory {
 
 	public void person() throws Exception {
 		try {
-			String url = Config.x_program_centerUrlRoot() + Applications.joinQueryUri("collect", "person");
+			String url = Config.url_x_program_center_jaxrs("collect", "person");
 			CipherConnectionAction.get(false, url);
 		} catch (Exception e) {
 			throw new Exception("CollectFactory create error.", e);

+ 228 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/StandardJaxrsAction.java

@@ -8,6 +8,12 @@ import java.util.Map.Entry;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
+import javax.persistence.Tuple;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.persistence.criteria.Selection;
 
 import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.commons.collections4.map.ListOrderedMap;
@@ -20,6 +26,7 @@ import com.x.base.core.project.bean.WrapCopier;
 import com.x.base.core.project.exception.ExceptionWhen;
 import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
+import com.x.base.core.project.tools.ListTools;
 
 public abstract class StandardJaxrsAction extends AbstractJaxrsAction {
 
@@ -1015,4 +1022,225 @@ public abstract class StandardJaxrsAction extends AbstractJaxrsAction {
 				: pageSize;
 	}
 
+	public <T extends JpaObject, W> ActionResult<List<W>> standardListNext(WrapCopier<T, W> copier, String id,
+			Integer count, String sequenceField, String order, Predicate predicate) throws Exception {
+		Class<T> tClass = (Class<T>) copier.getOrigClass();
+		Class<W> wClass = (Class<W>) copier.getDestClass();
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			// 先获取上一页最后一条的sequence值,如果有值的话,以此sequence值作为依据取后续的count条数据
+			Object sequence = null;
+			if (!StringUtils.equalsIgnoreCase(id, EMPTY_SYMBOL)) {
+				T t = emc.fetch(id, tClass, ListTools.toList(sequenceField));
+				if (null != t) {
+					sequence = PropertyUtils.getProperty(t, sequenceField);
+				}
+			}
+			EntityManager em = emc.get(tClass);
+			CriteriaBuilder cb = em.getCriteriaBuilder();
+			CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);
+			Root<T> root = cq.from(tClass);
+
+			if (null == predicate) {
+				predicate = cb.conjunction();
+			}
+
+			if (StringUtils.equalsIgnoreCase(order, DESC)) {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.lessThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.desc(root.get(sequenceField)));
+			} else {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.greaterThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.asc(root.get(sequenceField)));
+			}
+
+			List<Selection<?>> selections = new ArrayList<>();
+
+			List<String> fields = copier.getCopyFields();
+
+			for (String field : fields) {
+				selections.add(root.get(field));
+			}
+
+			List<Tuple> os = em.createQuery(cq.multiselect(selections))
+					.setMaxResults(Math.max(Math.min(count, list_max), list_min)).getResultList();
+
+			List<W> ws = new ArrayList<W>();
+
+			for (Tuple tuple : os) {
+				W w = wClass.newInstance();
+				for (int i = 0; i < selections.size(); i++) {
+					PropertyUtils.setProperty(w, fields.get(i), tuple.get(selections.get(i)));
+				}
+				ws.add(w);
+			}
+			ActionResult<List<W>> result = new ActionResult<>();
+			result.setData(ws);
+			// 设置查询结果的总条目数
+			result.setCount(this.count(emc, tClass, predicate));
+			return result;
+		}
+	}
+
+	public <T extends JpaObject, W> ActionResult<List<W>> standardListPrev(WrapCopier<T, W> copier, String id,
+			Integer count, String sequenceField, String order, Predicate predicate) throws Exception {
+		Class<T> tClass = (Class<T>) copier.getOrigClass();
+		Class<W> wClass = (Class<W>) copier.getDestClass();
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			// 先获取上一页最后一条的sequence值,如果有值的话,以此sequence值作为依据取后续的count条数据
+			Object sequence = null;
+			if (!StringUtils.equalsIgnoreCase(id, EMPTY_SYMBOL)) {
+				T t = emc.fetch(id, tClass, ListTools.toList(sequenceField));
+				if (null != t) {
+					sequence = PropertyUtils.getProperty(t, sequenceField);
+				}
+			}
+			EntityManager em = emc.get(tClass);
+			CriteriaBuilder cb = em.getCriteriaBuilder();
+			CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);
+			Root<T> root = cq.from(tClass);
+
+			if (null == predicate) {
+				predicate = cb.conjunction();
+			}
+
+			if (StringUtils.equalsIgnoreCase(order, DESC)) {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.greaterThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.desc(root.get(sequenceField)));
+			} else {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.lessThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.asc(root.get(sequenceField)));
+			}
+
+			List<Selection<?>> selections = new ArrayList<>();
+
+			List<String> fields = copier.getCopyFields();
+
+			for (String field : fields) {
+				selections.add(root.get(field));
+			}
+
+			List<Tuple> os = em.createQuery(cq.multiselect(selections))
+					.setMaxResults(Math.max(Math.min(count, list_max), list_min)).getResultList();
+
+			List<W> ws = new ArrayList<W>();
+
+			Tuple tuple = null;
+
+			for (int i = os.size() - 1; i >= 0; i--) {
+				tuple = os.get(i);
+				W w = wClass.newInstance();
+				for (int j = 0; j < selections.size(); j++) {
+					PropertyUtils.setProperty(w, fields.get(j), tuple.get(selections.get(j)));
+				}
+				ws.add(w);
+			}
+
+			ActionResult<List<W>> result = new ActionResult<>();
+			result.setData(ws);
+			// 设置查询结果的总条目数
+			result.setCount(this.count(emc, tClass, predicate));
+			return result;
+		}
+	}
+
+	public <T extends JpaObject> ActionResult<List<T>> standardListNext(Class<T> cls, String id, Integer count,
+			String sequenceField, String order, Predicate predicate) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			// 先获取上一页最后一条的sequence值,如果有值的话,以此sequence值作为依据取后续的count条数据
+			Object sequence = null;
+			if (!StringUtils.equalsIgnoreCase(id, EMPTY_SYMBOL)) {
+				T t = emc.fetch(id, cls, ListTools.toList(sequenceField));
+				if (null != t) {
+					sequence = PropertyUtils.getProperty(t, sequenceField);
+				}
+			}
+			EntityManager em = emc.get(cls);
+			CriteriaBuilder cb = em.getCriteriaBuilder();
+			CriteriaQuery<T> cq = cb.createQuery(cls);
+			Root<T> root = cq.from(cls);
+
+			if (null == predicate) {
+				predicate = cb.conjunction();
+			}
+
+			if (StringUtils.equalsIgnoreCase(order, DESC)) {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.lessThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.desc(root.get(sequenceField)));
+			} else {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.greaterThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.asc(root.get(sequenceField)));
+			}
+
+			List<T> os = em.createQuery(cq.select(root)).setMaxResults(Math.max(Math.min(count, list_max), list_min))
+					.getResultList();
+
+			ActionResult<List<T>> result = new ActionResult<>();
+			result.setData(new ArrayList<T>(os));
+			// 设置查询结果的总条目数
+			result.setCount(this.count(emc, cls, predicate));
+			return result;
+		}
+	}
+
+	public <T extends JpaObject> ActionResult<List<T>> standardListPrev(Class<T> cls, String id, Integer count,
+			String sequenceField, String order, Predicate predicate) throws Exception {
+		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
+			// 先获取上一页最后一条的sequence值,如果有值的话,以此sequence值作为依据取后续的count条数据
+			Object sequence = null;
+			if (!StringUtils.equalsIgnoreCase(id, EMPTY_SYMBOL)) {
+				T t = emc.fetch(id, cls, ListTools.toList(sequenceField));
+				if (null != t) {
+					sequence = PropertyUtils.getProperty(t, sequenceField);
+				}
+			}
+			EntityManager em = emc.get(cls);
+			CriteriaBuilder cb = em.getCriteriaBuilder();
+			CriteriaQuery<T> cq = cb.createQuery(cls);
+			Root<T> root = cq.from(cls);
+
+			if (null == predicate) {
+				predicate = cb.conjunction();
+			}
+
+			if (StringUtils.equalsIgnoreCase(order, DESC)) {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.greaterThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.desc(root.get(sequenceField)));
+			} else {
+				cq.where(null == sequence ? predicate
+						: cb.and(predicate, cb.lessThan(root.get(sequenceField), (Comparable) sequence)));
+				cq.orderBy(cb.asc(root.get(sequenceField)));
+			}
+
+			List<T> os = em.createQuery(cq.select(root)).setMaxResults(Math.max(Math.min(count, list_max), list_min))
+					.getResultList();
+
+			List<T> wos = new ArrayList<>();
+
+			for (int i = os.size() - 1; i >= 0; i--) {
+				wos.add(os.get(i));
+			}
+
+			ActionResult<List<T>> result = new ActionResult<>();
+			result.setData(wos);
+			// 设置查询结果的总条目数
+			result.setCount(this.count(emc, cls, predicate));
+			return result;
+		}
+	}
+
+	private <T extends JpaObject> Long count(EntityManagerContainer emc, Class<T> cls, Predicate predicate)
+			throws Exception {
+		EntityManager em = emc.get(cls);
+		CriteriaBuilder cb = em.getCriteriaBuilder();
+		CriteriaQuery<Long> cq = cb.createQuery(Long.class);
+		Root<T> root = cq.from(cls);
+		return em.createQuery(cq.select(cb.count(root)).where(predicate)).getSingleResult();
+	}
+
 }

+ 2 - 3
o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/fireschedule/ActionExecute.java

@@ -3,13 +3,12 @@ package com.x.base.core.project.jaxrs.fireschedule;
 import javax.servlet.ServletContext;
 import javax.ws.rs.core.Context;
 
-import org.quartz.Job;
-
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.jaxrs.WrapBoolean;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 
 class ActionExecute extends BaseAction {
 
@@ -21,7 +20,7 @@ class ActionExecute extends BaseAction {
 		ActionResult<Wo> result = new ActionResult<>();
 		com.x.base.core.project.Context ctx = com.x.base.core.project.Context.fromServletContext(servletContext);
 		Class<?> clz = Class.forName(className);
-		ctx.scheduleLocal((Class<Job>) clz);
+		ctx.scheduleLocal((Class<AbstractJob>) clz, 1);
 		Wo wo = new Wo();
 		wo.setValue(true);
 		result.setData(wo);

+ 12 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/jaxrs/fireschedule/ExceptionScheduleLastNotEnd.java

@@ -0,0 +1,12 @@
+package com.x.base.core.project.jaxrs.fireschedule;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionScheduleLastNotEnd extends PromptException {
+
+	private static final long serialVersionUID = -7954335762204386602L;
+
+	ExceptionScheduleLastNotEnd(String className, String application) {
+		super("abandon fire schedule className: {}, application: {}, last run not ended.", className, application);
+	}
+}

+ 2 - 2
o2server/x_base_core_project/src/main/java/com/x/base/core/project/logger/Audit.java

@@ -24,7 +24,7 @@ public class Audit {
 		this.start = new Date();
 		this.person = Objects.toString(person, "");
 		this.remoteAddress = Objects.toString(remoteAddress, "");
-		this.uri = Objects.toString(uri,"");
+		this.uri = Objects.toString(uri, "");
 		this.userAgent = Objects.toString(userAgent, "");
 		this.className = Objects.toString(className, "");
 	}
@@ -37,7 +37,7 @@ public class Audit {
 		if (Config.logLevel().audit().enable()) {
 			Date end = new Date();
 			long elapsed = end.getTime() - start.getTime();
-			PrintStream stream = (PrintStream) Config.resource(Config.RESOUCE_AUDITLOGPRINTSTREAM);
+			PrintStream stream = (PrintStream) Config.resource(Config.RESOURCE_AUDITLOGPRINTSTREAM);
 			stream.printf("%tF %tT,,,%d,,,%s,,,%s,,,%s,,,%s,,,%s,,,%s%n", end, end, elapsed, this.person,
 					this.remoteAddress, this.uri, this.userAgent, this.className,
 					MessageFormatter.arrayFormat(Objects.toString(message, ""), os).getMessage());

+ 5 - 5
o2server/x_base_core_project/src/main/java/com/x/base/core/project/logger/Logger.java

@@ -137,7 +137,7 @@ public class Logger {
 						parameters.put(PARAMETER_OCCURTIME, DateTools.now());
 						parameters.put(PARAMETER_LOGGERNAME, loggerName);
 						parameters.put(PARAMETER_MESSAGE, str);
-						String url = Config.x_program_centerUrlRoot() + "warnlog";
+						String url = Config.url_x_program_center_jaxrs("warnlog");
 						CipherConnectionAction.post(false, url, parameters);
 					} catch (Exception e) {
 						e.printStackTrace();
@@ -178,10 +178,10 @@ public class Logger {
 					parameters.put(PARAMETER_MESSAGE, e.getMessage());
 					parameters.put(PARAMETER_STACKTRACE, stackTraceString);
 					if (e instanceof PromptException) {
-						String url = Config.x_program_centerUrlRoot() + "prompterrorlog";
+						String url = Config.url_x_program_center_jaxrs("prompterrorlog");
 						CipherConnectionAction.post(false, url, parameters);
 					} else {
-						String url = Config.x_program_centerUrlRoot() + "unexpectederrorlog";
+						String url = Config.url_x_program_center_jaxrs("unexpectederrorlog");
 						CipherConnectionAction.post(false, url, parameters);
 					}
 				} catch (Exception e) {
@@ -230,10 +230,10 @@ public class Logger {
 					parameters.put(PARAMETER_REQUESTBODY, bodyString);
 					parameters.put(PARAMETER_REQUESTBODYLENGTH, bodyString.length());
 					if (e instanceof PromptException) {
-						String url = Config.x_program_centerUrlRoot() + "prompterrorlog";
+						String url = Config.url_x_program_center_jaxrs("prompterrorlog");
 						CipherConnectionAction.post(false, url, parameters);
 					} else {
-						String url = Config.x_program_centerUrlRoot() + "unexpectederrorlog";
+						String url = Config.url_x_program_center_jaxrs("unexpectederrorlog");
 						CipherConnectionAction.post(false, url, parameters);
 					}
 				} catch (Exception e) {

+ 37 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/AbstractJob.java

@@ -0,0 +1,37 @@
+package com.x.base.core.project.schedule;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import com.x.base.core.project.logger.Logger;
+import com.x.base.core.project.logger.LoggerFactory;
+
+public abstract class AbstractJob implements Job {
+
+	private static Logger logger = LoggerFactory.getLogger(AbstractJob.class);
+
+	private static final CopyOnWriteArrayList<String> LOCK = new CopyOnWriteArrayList<>();
+
+	public final void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+		try {
+			if (LOCK.contains(this.getClass().getName())) {
+				throw new ExceptionScheduleLastNotEnd(this.getClass().getName());
+			}
+			try {
+				LOCK.add(this.getClass().getName());
+				this.schedule(jobExecutionContext);
+			} finally {
+				LOCK.remove(this.getClass().getName());
+			}
+		} catch (Exception e) {
+			logger.error(e);
+			throw new JobExecutionException(e);
+		}
+	}
+
+	public abstract void schedule(JobExecutionContext jobExecutionContext) throws Exception;
+
+}

+ 12 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ExceptionScheduleLastNotEnd.java

@@ -0,0 +1,12 @@
+package com.x.base.core.project.schedule;
+
+import com.x.base.core.project.exception.PromptException;
+
+class ExceptionScheduleLastNotEnd extends PromptException {
+
+	private static final long serialVersionUID = -7954335762204386602L;
+
+	ExceptionScheduleLastNotEnd(String className) {
+		super("abandon fire schedule className: {}, last run not ended.", className);
+	}
+}

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/JobReportListener.java

@@ -33,7 +33,7 @@ public class JobReportListener implements JobListener {
 		if (null != jobExecutionException) {
 			ScheduleLogRequest request = new ScheduleLogRequest(jobExecutionContext, jobExecutionException);
 			try {
-				CipherConnectionAction.post(false, Config.x_program_centerUrlRoot() + "schedule/report", request);
+				CipherConnectionAction.post(false, Config.url_x_program_center_jaxrs("schedule", "report"), request);
 			} catch (Exception e) {
 				logger.error(e);
 			}

+ 0 - 207
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ReportToCenter.java

@@ -1,207 +0,0 @@
-package com.x.base.core.project.schedule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.quartz.Job;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-import com.x.base.core.project.Context;
-import com.x.base.core.project.config.Config;
-import com.x.base.core.project.connection.ActionResponse;
-import com.x.base.core.project.connection.CipherConnectionAction;
-import com.x.base.core.project.gson.GsonPropertyObject;
-import com.x.base.core.project.tools.ListTools;
-
-public class ReportToCenter implements Job {
-
-	public static int INTERVAL = 45;
-
-	private static final String DATAMAP_ATTRIBUTE_CONTEXT = "context";
-
-	private Context context;
-
-	public ReportToCenter() {
-	}
-
-	public ReportToCenter(Context context) {
-		this.context = context;
-	}
-
-	public void execute() throws JobExecutionException {
-		Echo echo = this.send(context);
-		this.updateApplications(context, echo.getApplicationsToken());
-	}
-
-	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
-		this.context = (Context) jobExecutionContext.getMergedJobDataMap().get(DATAMAP_ATTRIBUTE_CONTEXT);
-		Echo echo = this.send(context);
-		this.updateApplications(context, echo.getApplicationsToken());
-	}
-
-	private void updateApplications(Context context, String applicationsToken) {
-		if ((null == context.applications())
-				|| (!StringUtils.equals(context.applications().getToken(), applicationsToken))) {
-			context.loadApplications();
-		}
-	}
-
-	private Echo send(Context context) throws JobExecutionException {
-		try {
-			Report report = this.conreteReport(context);
-			ActionResponse response = CipherConnectionAction.put(false,
-					Config.x_program_centerUrlRoot() + "center/report/application", report);
-			return response.getData(Echo.class);
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw new JobExecutionException(context.clazz() + " send error.", e);
-		}
-	}
-
-	private Report conreteReport(Context context) throws Exception {
-		Report report = new Report();
-		report.setClassName(context.clazz().getName());
-		report.setContextPath(context.contextPath());
-		report.setName(context.name());
-		report.setNode(Config.node());
-		report.setToken(context.token());
-		report.setWeight(context.weight());
-		report.setSslEnable(context.sslEnable());
-		report.setScheduleLocalRequestList(context.getScheduleLocalRequestList());
-		report.setScheduleRequestList(context.getScheduleRequestList());
-		return report;
-	}
-
-	public static class Report extends GsonPropertyObject {
-
-		private String className;
-		private String name;
-		private String contextPath;
-		private String node;
-		private String token;
-		private Integer weight;
-		private Boolean sslEnable;
-
-		private List<ScheduleLocalRequest> scheduleLocalRequestList = new ArrayList<>();
-
-		private List<ScheduleRequest> scheduleRequestList = new ArrayList<>();
-
-		public String getClassName() {
-			return className;
-		}
-
-		public void setClassName(String className) {
-			this.className = className;
-		}
-
-		public String getToken() {
-			return token;
-		}
-
-		public void setToken(String token) {
-			this.token = token;
-		}
-
-		public String getNode() {
-			return node;
-		}
-
-		public void setNode(String node) {
-			this.node = node;
-		}
-
-		public Integer getWeight() {
-			return weight;
-		}
-
-		public void setWeight(Integer weight) {
-			this.weight = weight;
-		}
-
-		public Boolean getSslEnable() {
-			return sslEnable;
-		}
-
-		public void setSslEnable(Boolean sslEnable) {
-			this.sslEnable = sslEnable;
-		}
-
-		public class ClockSchedule {
-
-			public ClockSchedule(String clockTaskClassName, String cron) {
-				this.clockTaskClassName = clockTaskClassName;
-				this.cron = cron;
-			}
-
-			private String clockTaskClassName;
-			private String cron;
-
-			public String getClockTaskClassName() {
-				return clockTaskClassName;
-			}
-
-			public void setClockTaskClassName(String clockTaskClassName) {
-				this.clockTaskClassName = clockTaskClassName;
-			}
-
-			public String getCron() {
-				return cron;
-			}
-
-			public void setCron(String cron) {
-				this.cron = cron;
-			}
-
-		}
-
-		public List<ScheduleLocalRequest> getScheduleLocalRequestList() {
-			return scheduleLocalRequestList;
-		}
-
-		public void setScheduleLocalRequestList(List<ScheduleLocalRequest> scheduleLocalRequestList) {
-			this.scheduleLocalRequestList = scheduleLocalRequestList;
-		}
-
-		public List<ScheduleRequest> getScheduleRequestList() {
-			return scheduleRequestList;
-		}
-
-		public void setScheduleRequestList(List<ScheduleRequest> scheduleRequestList) {
-			this.scheduleRequestList = scheduleRequestList;
-		}
-
-		public String getContextPath() {
-			return contextPath;
-		}
-
-		public void setContextPath(String contextPath) {
-			this.contextPath = contextPath;
-		}
-
-		public String getName() {
-			return name;
-		}
-
-		public void setName(String name) {
-			this.name = name;
-		}
-	}
-
-	public static class Echo extends GsonPropertyObject {
-
-		private String applicationsToken;
-
-		public String getApplicationsToken() {
-			return applicationsToken;
-		}
-
-		public void setApplicationsToken(String applicationsToken) {
-			this.applicationsToken = applicationsToken;
-		}
-
-	}
-
-}

+ 0 - 20
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleLocalRequest.java

@@ -11,16 +11,12 @@ public class ScheduleLocalRequest extends GsonPropertyObject {
 
 	public ScheduleLocalRequest(JobDetail jobDetail, String cron, Integer delay, Integer interval) {
 		this.className = jobDetail.getKey().getName();
-		this.application = jobDetail.getKey().getGroup();
-		this.node = jobDetail.getDescription();
 		this.cron = cron;
 		this.delay = delay;
 		this.interval = interval;
 	}
 
 	private String className;
-	private String application;
-	private String node;
 	private String cron;
 	private Integer delay;
 	private Integer interval;
@@ -33,22 +29,6 @@ public class ScheduleLocalRequest extends GsonPropertyObject {
 		this.className = className;
 	}
 
-	public String getApplication() {
-		return application;
-	}
-
-	public void setApplication(String application) {
-		this.application = application;
-	}
-
-	public String getNode() {
-		return node;
-	}
-
-	public void setNode(String node) {
-		this.node = node;
-	}
-
 	public String getCron() {
 		return cron;
 	}

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleLogRequest.java

@@ -34,7 +34,7 @@ public class ScheduleLogRequest extends GsonPropertyObject {
 		this.node = jobDetail.getDescription();
 		this.type = jobExecutionContext.getTrigger().getDescription();
 		this.elapsed = jobExecutionContext.getJobRunTime();
-		this.fireTime = jobExecutionContext.getFireTime();
+		this.fireTime = jobExecutionContext.getNextFireTime();
 		if (null != jobExecutionException) {
 			this.stackTrace = ExceptionUtils.getStackTrace(jobExecutionException);
 			this.success = false;

+ 8 - 17
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/ScheduleRequest.java

@@ -1,5 +1,7 @@
 package com.x.base.core.project.schedule;
 
+import java.util.Date;
+
 import org.quartz.Job;
 
 import com.x.base.core.project.gson.GsonPropertyObject;
@@ -9,17 +11,14 @@ public class ScheduleRequest extends GsonPropertyObject {
 	public ScheduleRequest() {
 	}
 
-	public <T extends Job> ScheduleRequest(Class<T> cls, String application, String node, String cron) {
+	public <T extends Job> ScheduleRequest(Class<T> cls, String node, String cron) {
 		this.className = cls.getName();
-		this.application = application;
-		this.node = node;
 		this.cron = cron;
 	}
 
 	private String className;
-	private String application;
-	private String node;
 	private String cron;
+	private Date lastStartTime;
 
 	public String getClassName() {
 		return className;
@@ -29,20 +28,12 @@ public class ScheduleRequest extends GsonPropertyObject {
 		this.className = className;
 	}
 
-	public String getApplication() {
-		return application;
-	}
-
-	public void setApplication(String application) {
-		this.application = application;
-	}
-
-	public String getNode() {
-		return node;
+	public Date getLastStartTime() {
+		return lastStartTime;
 	}
 
-	public void setNode(String node) {
-		this.node = node;
+	public void setLastStartTime(Date lastStartTime) {
+		this.lastStartTime = lastStartTime;
 	}
 
 	public String getCron() {

+ 0 - 14
o2server/x_base_core_project/src/main/java/com/x/base/core/project/schedule/SchedulerFactoryProperties.java

@@ -22,20 +22,6 @@ public class SchedulerFactoryProperties extends Properties {
 		properties.setProperty("org.quartz.jobStore.misfireThreshold", "60000");
 		properties.setProperty("org.quartz.jobStore.class", "org.quartz.simpl.RAMJobStore");
 		properties.setProperty("log4j.logger.org.quartz", "OFF");
-		// org.quartz.scheduler.instanceName: DefaultQuartzScheduler
-		// org.quartz.scheduler.rmi.export: false
-		// org.quartz.scheduler.rmi.proxy: false
-		// org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
-		//
-		// org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
-		// org.quartz.threadPool.threadCount: 10
-		// org.quartz.threadPool.threadPriority: 5
-		// org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread:
-		// true
-		//
-		// org.quartz.jobStore.misfireThreshold: 60000
-		//
-		// org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
 		return properties;
 	}
 

+ 12 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/CronTools.java

@@ -0,0 +1,12 @@
+package com.x.base.core.project.tools;
+
+import java.util.Date;
+
+import org.quartz.CronExpression;
+
+public class CronTools {
+	public static Date next(String expression, Date lastEndDate) throws Exception {
+		CronExpression cron = new CronExpression(expression);
+		return cron.getNextValidTimeAfter(lastEndDate == null ? DateTools.parse("2018-01-01 00:00:00") : lastEndDate);
+	}
+}

+ 39 - 0
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/DateTools.java

@@ -1,5 +1,6 @@
 package com.x.base.core.project.tools;
 
+import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Objects;
@@ -537,4 +538,42 @@ public class DateTools {
 		}
 		return calendar.getTime();
 	}
+	
+	  /** 
+	  * 判断当前日期是星期几
+	  * @param dateTime 修要判断的时间 
+	  * @return dayForWeek 判断结果
+	  * @Exception 发生异常
+	  */  
+	public static int dayForWeek(String dateTime ) throws Exception {
+		Calendar c = Calendar.getInstance();
+		c.setTime( DateUtils.parseDate( dateTime, format_yyyyMMdd) ); 
+		int dayForWeek = 0 ;
+		if (c.get(Calendar.DAY_OF_WEEK) == 1 ){ 
+			dayForWeek = 7;
+		}else {
+			dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
+		}
+		return dayForWeek; 
+	}
+	
+	 /** 
+	  * 判断当前日期是星期几
+	  * @param dateTime 修要判断的时间 
+	  * @return dayForWeek 判断结果
+	  * @Exception 发生异常
+	  */  
+	public static int dayForWeek( Date dateTime ) throws Exception {
+		Calendar c = Calendar.getInstance();
+		c.setTime( dateTime ); 
+		int dayForWeek = 0 ;
+		if (c.get(Calendar.DAY_OF_WEEK) == 1 ){ 
+			dayForWeek = 7;
+		}else {
+			dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
+		}
+		return dayForWeek; 
+	}
+
+	
 }

+ 119 - 26
o2server/x_base_core_project/src/main/java/com/x/base/core/project/tools/DocumentTools.java

@@ -6,24 +6,45 @@ import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.Objects;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.tika.Tika;
 
 import com.x.base.core.project.config.Config;
 import com.x.base.core.project.connection.ActionResponse;
+import com.x.base.core.project.connection.ConnectionAction;
+import com.x.base.core.project.exception.ExceptionUnsupportedMediaType;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.http.HttpMediaType;
 import com.x.base.core.project.jaxrs.WrapString;
 
 public class DocumentTools {
 
-	private static final String CL = "\r\n";
+	private static final String CRLF = StringUtils.CR + StringUtils.LF;
 	private static final String twoHyphens = "--";
 
+	public static final String MEDIATYPE_DOC = "application/msword";
+	public static final String MEDIATYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
+
 	public static byte[] toPdf(String fileName, byte[] bytes, String stamp) throws Exception {
 
+		Config.collect().validate();
+
+		Tika tika = new Tika();
+		String type = tika.detect(bytes, fileName);
+
+		switch (Objects.toString(type, "")) {
+		case MEDIATYPE_DOC:
+			break;
+		case MEDIATYPE_DOCX:
+			break;
+		default:
+			throw new ExceptionUnsupportedMediaType(type);
+		}
+
 		URL serverUrl = new URL(Config.collect().url() + "/o2_collect_assemble/jaxrs/document/to/pdf");
 
 		HttpURLConnection connection = (HttpURLConnection) serverUrl.openConnection();
@@ -38,27 +59,27 @@ public class DocumentTools {
 		try (OutputStream out = connection.getOutputStream();
 				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out))) {
 			writer.write(twoHyphens + boundary);
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Disposition: form-data; name=\"file\"; filename=\""
 					+ (StringUtils.isEmpty(fileName) ? StringTools.uniqueToken() : fileName) + "\"");
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Type: " + HttpMediaType.APPLICATION_OCTET_STREAM);
-			writer.write(CL);
-			writer.write(CL);
+			writer.write(CRLF);
+			writer.write(CRLF);
 			writer.flush();
 			out.write(bytes);
 			out.flush();
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write(twoHyphens + boundary);
 			if (StringUtils.isNotEmpty(stamp)) {
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write("Content-Disposition: form-data; name=\"stamp\"");
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write("Content-Type: " + HttpMediaType.TEXT_PLAIN);
-				writer.write(CL);
-				writer.write(CL);
+				writer.write(CRLF);
+				writer.write(CRLF);
 				writer.write(stamp);
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write(twoHyphens + boundary);
 			}
 			writer.write(twoHyphens);
@@ -82,6 +103,20 @@ public class DocumentTools {
 
 	public static byte[] toImage(String fileName, byte[] bytes, String stamp, Integer page) throws Exception {
 
+		Config.collect().validate();
+
+		Tika tika = new Tika();
+		String type = tika.detect(bytes, fileName);
+
+		switch (Objects.toString(type, "")) {
+		case MEDIATYPE_DOC:
+			break;
+		case MEDIATYPE_DOCX:
+			break;
+		default:
+			throw new ExceptionUnsupportedMediaType(type);
+		}
+
 		URL serverUrl = new URL(Config.collect().url() + "/o2_collect_assemble/jaxrs/document/to/image");
 
 		HttpURLConnection connection = (HttpURLConnection) serverUrl.openConnection();
@@ -96,36 +131,36 @@ public class DocumentTools {
 		try (OutputStream out = connection.getOutputStream();
 				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out))) {
 			writer.write(twoHyphens + boundary);
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Disposition: form-data; name=\"file\"; filename=\""
 					+ (StringUtils.isEmpty(fileName) ? StringTools.uniqueToken() : fileName) + "\"");
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Type: " + HttpMediaType.APPLICATION_OCTET_STREAM);
-			writer.write(CL);
-			writer.write(CL);
+			writer.write(CRLF);
+			writer.write(CRLF);
 			writer.flush();
 			out.write(bytes);
 			out.flush();
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write(twoHyphens + boundary);
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Disposition: form-data; name=\"page\"");
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write("Content-Type: " + HttpMediaType.TEXT_PLAIN);
-			writer.write(CL);
-			writer.write(CL);
+			writer.write(CRLF);
+			writer.write(CRLF);
 			writer.write("" + ((page == null || page < 0) ? 0 : page));
-			writer.write(CL);
+			writer.write(CRLF);
 			writer.write(twoHyphens + boundary);
 			if (StringUtils.isNotEmpty(stamp)) {
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write("Content-Disposition: form-data; name=\"stamp\"");
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write("Content-Type: " + HttpMediaType.TEXT_PLAIN);
-				writer.write(CL);
-				writer.write(CL);
+				writer.write(CRLF);
+				writer.write(CRLF);
 				writer.write(stamp);
-				writer.write(CL);
+				writer.write(CRLF);
 				writer.write(twoHyphens + boundary);
 			}
 			writer.write(twoHyphens);
@@ -147,4 +182,62 @@ public class DocumentTools {
 
 	}
 
+	public static byte[] docToWord(String fileName, String content) throws Exception {
+
+		Config.collect().validate();
+
+		DocToWordReq req = new DocToWordReq();
+		req.setName(Config.collect().getName());
+		req.setPassword(Config.collect().getPassword());
+		req.setFileName(fileName);
+		req.setContent(content);
+		ActionResponse response = ConnectionAction
+				.post(Config.collect().url("/o2_collect_assemble/jaxrs/document/doc/to/word"), null, req);
+		WrapString wrap = response.getData(WrapString.class);
+		if (StringUtils.isNotEmpty(wrap.getValue())) {
+			return Base64.decodeBase64(wrap.getValue());
+		}
+		return null;
+	}
+
+	public static class DocToWordReq {
+
+		public String getName() {
+			return name;
+		}
+
+		public String getPassword() {
+			return password;
+		}
+
+		public String getFileName() {
+			return fileName;
+		}
+
+		public String getContent() {
+			return content;
+		}
+
+		private String name;
+		private String password;
+		private String fileName;
+		private String content;
+
+		public void setName(String name) {
+			this.name = name;
+		}
+
+		public void setPassword(String password) {
+			this.password = password;
+		}
+
+		public void setFileName(String fileName) {
+			this.fileName = fileName;
+		}
+
+		public void setContent(String content) {
+			this.content = content;
+		}
+	}
+
 }

+ 1 - 1
o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_file_assemble_control.java

@@ -8,7 +8,7 @@ import com.x.base.core.project.annotation.ModuleType;
 @Module(type = ModuleType.ASSEMBLE, category = ModuleCategory.OFFICIAL, name = "云文件", packageName = "com.x.file.assemble.control", containerEntities = {
 		"com.x.file.core.entity.personal.Folder", "com.x.file.core.entity.personal.Folder2", "com.x.file.core.entity.personal.Attachment",
 		"com.x.file.core.entity.personal.Attachment2", "com.x.file.core.entity.personal.Share", "com.x.file.core.entity.open.File",
-		"com.x.file.core.entity.open.OriginFile" },
+		"com.x.file.core.entity.open.OriginFile","com.x.file.core.entity.personal.Recycle" },
 		storageTypes = { StorageType.file }, storeJars = { "x_file_core_entity", "x_organization_core_express", "x_organization_core_entity" })
 public class x_file_assemble_control extends Deployable {
 

+ 0 - 13
o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_hotpic_assemble_control.java

@@ -11,17 +11,4 @@ import com.x.base.core.project.annotation.ModuleType;
 				"x_organization_core_entity", "x_organization_core_express", "x_hotpic_core_entity",
 				"x_cms_core_entity", "x_bbs_core_entity" })
 public class x_hotpic_assemble_control extends Deployable {
-
-//	public x_hotpic_assemble_control() {
-//		super();
-//		dependency.containerEntities.add("com.x.hotpic.entity.HotPictureInfo");
-//		dependency.containerEntities.add("com.x.bbs.entity.BBSSubjectInfo");
-//		dependency.containerEntities.add("com.x.cms.core.entity.Document");
-//		dependency.storageTypes.add(StorageType.file.toString());
-//		dependency.storeJars.add(x_organization_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_organization_core_express.class.getSimpleName());
-//		dependency.storeJars.add(x_hotpic_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_cms_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_bbs_core_entity.class.getSimpleName());
-//	}
 }

+ 0 - 17
o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_organization_assemble_personal.java

@@ -15,21 +15,4 @@ import com.x.base.core.project.annotation.ModuleType;
 				"x_organization_core_express" })
 public class x_organization_assemble_personal extends Deployable {
 
-//	public x_organization_assemble_personal() {
-//		super();
-//		dependency.containerEntities.add("com.x.organization.core.entity.Group");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Role");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Person");
-//		dependency.containerEntities.add("com.x.organization.core.entity.PersonAttribute");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Identity");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Unit");
-//		dependency.containerEntities.add("com.x.organization.core.entity.UnitAttribute");
-//		dependency.containerEntities.add("com.x.organization.core.entity.UnitDuty");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Custom");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Definition");
-//		dependency.containerEntities.add("com.x.organization.core.entity.accredit.Trust");
-//		dependency.containerEntities.add("com.x.organization.core.entity.accredit.TrustLog");
-//		dependency.storeJars.add(x_organization_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_organization_core_express.class.getSimpleName());
-//	}
 }

+ 5 - 49
o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_processplatform_assemble_designer.java

@@ -14,10 +14,12 @@ import com.x.base.core.project.annotation.ModuleType;
 		"com.x.processplatform.core.entity.content.WorkLog", "com.x.processplatform.core.entity.element.Invoke",
 		"com.x.processplatform.core.entity.element.Message", "com.x.processplatform.core.entity.element.Split",
 		"com.x.processplatform.core.entity.element.File", "com.x.processplatform.core.entity.element.Form",
-		"com.x.processplatform.core.entity.element.FormField", "com.x.processplatform.core.entity.element.TemplateForm",
+		"com.x.processplatform.core.entity.element.FormVersion", "com.x.processplatform.core.entity.element.FormField",
+		"com.x.processplatform.core.entity.element.TemplateForm",
 		"com.x.processplatform.core.entity.element.Application", "com.x.processplatform.core.entity.element.Script",
-		"com.x.processplatform.core.entity.element.Merge", "com.x.processplatform.core.entity.element.Agent",
-		"com.x.processplatform.core.entity.element.Process", "com.x.processplatform.core.entity.element.Choice",
+		"com.x.processplatform.core.entity.element.ScriptVersion", "com.x.processplatform.core.entity.element.Merge",
+		"com.x.processplatform.core.entity.element.Agent", "com.x.processplatform.core.entity.element.Process",
+		"com.x.processplatform.core.entity.element.ProcessVersion", "com.x.processplatform.core.entity.element.Choice",
 		"com.x.processplatform.core.entity.element.Delay", "com.x.processplatform.core.entity.element.Parallel",
 		"com.x.processplatform.core.entity.element.Begin", "com.x.processplatform.core.entity.element.Cancel",
 		"com.x.processplatform.core.entity.element.Embed", "com.x.processplatform.core.entity.element.Service",
@@ -31,50 +33,4 @@ import com.x.base.core.project.annotation.ModuleType;
 						"x_query_dynamic_entity" }, storageTypes = { StorageType.processPlatform })
 public class x_processplatform_assemble_designer extends Deployable {
 
-//	public x_processplatform_assemble_designer() {
-//		super();
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Attachment");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Read");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.ReadCompleted");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Review");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Hint");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.SerialNumber");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Task");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.TaskCompleted");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.Work");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.WorkCompleted");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.content.WorkLog");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Invoke");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Message");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Split");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.File");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Form");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.FormField");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.TemplateForm");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Application");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Script");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Merge");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Agent");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Process");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Choice");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Delay");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Parallel");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Begin");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Cancel");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Embed");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Service");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Manual");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.Route");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.End");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.ApplicationDict");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.ApplicationDictItem");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.QueryView");
-//		dependency.containerEntities.add("com.x.processplatform.core.entity.element.QueryStat");
-//		dependency.containerEntities.add("com.x.query.core.entity.Item");
-//		dependency.storageTypes.add(StorageType.processPlatform.toString());
-//		dependency.storeJars.add(x_organization_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_organization_core_express.class.getSimpleName());
-//		dependency.storeJars.add(x_processplatform_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_query_core_entity.class.getSimpleName());
-//	}
 }

+ 5 - 49
o2server/x_base_core_project/src/main/java/com/x/base/core/project/x_program_center.java

@@ -15,56 +15,12 @@ import com.x.base.core.project.annotation.ModuleType;
 		"com.x.organization.core.entity.Person", "com.x.organization.core.entity.Identity",
 		"com.x.organization.core.entity.PersonAttribute", "com.x.organization.core.entity.Unit",
 		"com.x.organization.core.entity.UnitAttribute", "com.x.organization.core.entity.UnitDuty",
-		"com.x.general.core.entity.area.District", "com.x.program.center.core.entity.Schedule",
-		"com.x.program.center.core.entity.ScheduleLocal",
-		"com.x.program.center.core.entity.ScheduleLog" }, storeJars = { "x_organization_core_express",
-				"x_program_center_core_entity", "x_attendance_core_entity", "x_cms_core_entity",
-				"x_message_core_entity", "x_component_core_entity", "x_file_core_entity", "x_meeting_core_entity",
-				"x_okr_core_entity", "x_organization_core_entity", "x_processplatform_core_entity",
-				"x_query_core_entity", "x_portal_core_entity",
+		"com.x.general.core.entity.area.District", "com.x.program.center.core.entity.ScheduleLog" }, storeJars = {
+				"x_organization_core_express", "x_program_center_core_entity", "x_attendance_core_entity",
+				"x_cms_core_entity", "x_message_core_entity", "x_component_core_entity", "x_file_core_entity",
+				"x_meeting_core_entity", "x_okr_core_entity", "x_organization_core_entity",
+				"x_processplatform_core_entity", "x_query_core_entity", "x_portal_core_entity",
 				"x_general_core_entity" }, dynamicJars = { "x_query_dynamic_entity" })
 public class x_program_center extends Deployable {
 
-//	public x_program_center() {
-//		super();
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Agent");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Invoke");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Captcha");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Code");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.PromptErrorLog");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.UnexpectedErrorLog");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Structure");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.WarnLog");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.validation.Meta");
-//		dependency.containerEntities.add("com.x.portal.core.entity.Page");
-//		dependency.containerEntities.add("com.x.portal.core.entity.Portal");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Group");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Custom");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Role");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Person");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Identity");
-//		dependency.containerEntities.add("com.x.organization.core.entity.PersonAttribute");
-//		dependency.containerEntities.add("com.x.organization.core.entity.Unit");
-//		dependency.containerEntities.add("com.x.organization.core.entity.UnitAttribute");
-//		dependency.containerEntities.add("com.x.organization.core.entity.UnitDuty");
-//		dependency.containerEntities.add("com.x.general.core.entity.area.District");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.Schedule");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.ScheduleLocal");
-//		dependency.containerEntities.add("com.x.program.center.core.entity.ScheduleLog");
-//		dependency.storeJars.add(x_organization_core_express.class.getSimpleName());
-//		dependency.storeJars.add(x_program_center_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_attendance_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_cms_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_message_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_component_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_file_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_meeting_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_okr_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_organization_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_processplatform_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_query_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_portal_core_entity.class.getSimpleName());
-//		dependency.storeJars.add(x_general_core_entity.class.getSimpleName());
-//		dependency.dynamicJars.add("x_query_dynamic_entity");
-//	}
 }

+ 13 - 0
o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/gson/Foo.java

@@ -1,5 +1,10 @@
 package com.x.base.core.project.test.gson;
 
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.junit.Test;
+
 import com.google.gson.annotations.SerializedName;
 
 public class Foo {
@@ -25,4 +30,12 @@ public class Foo {
 		this.bbb = bbb;
 	}
 
+	@Test
+	public void test() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+		Foo foo = new Foo();
+		System.out.println(PropertyUtils.isReadable(foo, "aaaaa"));
+		//System.out.println(PropertyUtils.getProperty(foo, "aaaaa"));
+
+	}
+
 }

+ 30 - 0
o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/lambda/TestClient2.java

@@ -1,13 +1,43 @@
 package com.x.base.core.project.test.lambda;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentSkipListMap;
+
 import org.junit.Test;
 
+import com.x.base.core.project.gson.XGsonBuilder;
+
 public class TestClient2 {
 
 	@Test
 	public void test1() {
 
+		HashMap<String, Integer> hash = new HashMap<>();
+		ConcurrentSkipListMap<String, Integer> map = new ConcurrentSkipListMap<>();
+		hash.put("AAA", 9);
+		hash.put("DDD", 8);
+		hash.put("BBB", 7);
+		hash.put("CCC", 6);
+		hash.entrySet().stream().sorted((o1, o2) -> {
+			return o1.getValue() - o2.getValue();
+		}).forEachOrdered(o -> {
+			System.out.println("key:" + o.getKey());
+			map.put(o.getKey(), o.getValue());
+		});
+		System.out.println(XGsonBuilder.toJson(map));
 
+		List<String> list = Collections.synchronizedList(new ArrayList<String>());
+		list.add("aaa");
+		list.add("ccc");
+		list.add("bbb");
+		Iterator<String> i = list.iterator(); // Must be in synchronized block
+		while (i.hasNext()) {
+			System.out.println(i.next());
+		}
 	}
 
 }

+ 24 - 4
o2server/x_base_core_project/src/test/java/com/x/base/core/project/test/list/TestClient.java

@@ -1,11 +1,31 @@
 package com.x.base.core.project.test.list;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.TreeMap;
 
 import org.junit.Test;
 
-import com.x.base.core.project.tools.ListTools;
-
 public class TestClient {
+
+	@Test
+	public void test() {
+		String a1 = "1";
+		String a3 = "3";
+		String a5 = "5";
+		String a7 = "7";
+
+		TreeMap<Integer, String> tree = new TreeMap<>();
+
+		int cursor = 0;
+		cursor = cursor + Integer.parseInt(a1);
+		tree.put(cursor, a1);
+		cursor = cursor + Integer.parseInt(a3);
+		tree.put(cursor, a3);
+		cursor = cursor + Integer.parseInt(a5);
+		tree.put(cursor, a5);
+		cursor = cursor + Integer.parseInt(a7);
+		tree.put(cursor, a7);
+
+		System.out.println(tree.tailMap(1, true).firstEntry().getValue());
+	}
+
 }

+ 1 - 0
o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/ApplicationServletContextListener.java

@@ -14,6 +14,7 @@ public class ApplicationServletContextListener implements ServletContextListener
 		try {
 			ThisApplication.context = Context.concrete(servletContextEvent);
 			ThisApplication.init();
+			ThisApplication.context().regist();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 3 - 4
o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/SubjectReplyTotalStatisticTask.java

@@ -2,12 +2,11 @@ package com.x.bbs.assemble.control.schedule;
 
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.tools.ListTools;
 import com.x.bbs.assemble.control.service.BBSForumSubjectStatisticService;
 import com.x.bbs.assemble.control.service.BBSSectionInfoServiceAdv;
@@ -21,7 +20,7 @@ import com.x.bbs.entity.BBSSubjectInfo;
  * @author LIYI
  *
  */
-public class SubjectReplyTotalStatisticTask implements Job {
+public class SubjectReplyTotalStatisticTask extends AbstractJob {
 
 	private Logger logger = LoggerFactory.getLogger(SubjectReplyTotalStatisticTask.class);
 	private BBSSubjectInfoService subjectInfoService = new BBSSubjectInfoService();
@@ -29,7 +28,7 @@ public class SubjectReplyTotalStatisticTask implements Job {
 	private BBSForumSubjectStatisticService forumSubjectStatisticService = new BBSForumSubjectStatisticService();
 
 	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		List<BBSSectionInfo> sectionList = null;
 		try {
 			sectionList = sectionInfoServiceAdv.listAll();

+ 4 - 5
o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/SubjectTotalStatisticTask.java

@@ -2,12 +2,12 @@ package com.x.bbs.assemble.control.schedule;
 
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
 
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.tools.ListTools;
 import com.x.bbs.assemble.control.service.BBSForumInfoServiceAdv;
 import com.x.bbs.assemble.control.service.BBSForumSubjectStatisticService;
@@ -19,19 +19,18 @@ import com.x.bbs.entity.BBSForumInfo;
  * @author LIYI
  *
  */
-public class SubjectTotalStatisticTask implements Job {
+public class SubjectTotalStatisticTask extends AbstractJob {
 
 	private Logger logger = LoggerFactory.getLogger(SubjectTotalStatisticTask.class);
 	private BBSForumInfoServiceAdv forumInfoServiceAdv = new BBSForumInfoServiceAdv();
 	private BBSForumSubjectStatisticService forumSubjectStatisticService = new BBSForumSubjectStatisticService();
 
 	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		List<BBSForumInfo> forumInfoList = null;
-
 		try {
 			forumInfoList = forumInfoServiceAdv.listAll();
-			if ( ListTools.isNotEmpty( forumInfoList )) {
+			if (ListTools.isNotEmpty(forumInfoList)) {
 				forumSubjectStatisticService.statisticSubjectTotalAndReplayTotalForForum(forumInfoList);
 			}
 			logger.info("Timertask[SubjectReplyTotalStatisticTask] completed and excute success.");

+ 3 - 4
o2server/x_bbs_assemble_control/src/main/java/com/x/bbs/assemble/control/schedule/UserSubjectReplyPermissionStatisticTask.java

@@ -2,14 +2,13 @@ package com.x.bbs.assemble.control.schedule;
 
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.google.gson.Gson;
 import com.x.base.core.project.gson.XGsonBuilder;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.tools.ListTools;
 import com.x.bbs.assemble.control.service.BBSOperationRecordService;
 import com.x.bbs.assemble.control.service.BBSPermissionInfoService;
@@ -25,7 +24,7 @@ import com.x.bbs.assemble.control.service.bean.RoleAndPermission;
  * @author LIYI
  *
  */
-public class UserSubjectReplyPermissionStatisticTask implements Job {
+public class UserSubjectReplyPermissionStatisticTask extends AbstractJob {
 
 	private Logger logger = LoggerFactory.getLogger(UserSubjectReplyPermissionStatisticTask.class);
 
@@ -37,7 +36,7 @@ public class UserSubjectReplyPermissionStatisticTask implements Job {
 	private BBSRoleInfoService roleInfoService = new BBSRoleInfoService();
 
 	@Override
-	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		process();
 		logger.info("Timertask[UserSubjectReplyStatisticTask] completed and excute success.");
 	}

+ 132 - 43
o2server/x_bbs_assemble_control/src/main/webapp/jest/describe.js

@@ -1,7 +1,6 @@
 var Describe = function() {
 	// 20180730
 }
-
 Describe.splitValue = function(str) {
 	if (str) {
 		if (str.length > 0) {
@@ -10,7 +9,6 @@ Describe.splitValue = function(str) {
 	}
 	return [];
 }
-
 Describe.joinValue = function(o, split) {
 	var s = ',';
 	if (split) {
@@ -23,7 +21,6 @@ Describe.joinValue = function(o, split) {
 	}
 	return o;
 }
-
 Describe.doPost = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -59,7 +56,6 @@ Describe.doPost = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doPut = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -95,7 +91,6 @@ Describe.doPut = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doGet = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -119,7 +114,6 @@ Describe.doGet = function(address, m) {
 		window.open(address, '_blank');
 	}
 }
-
 Describe.doDelete = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -155,7 +149,6 @@ Describe.doDelete = function(address, m) {
 		});
 	}
 }
-
 Describe.writeOut = function(outs, json) {
 	if (outs && (outs.length) && json && json.data) {
 		$.each(Object.keys(json.data), function(i, k) {
@@ -164,14 +157,98 @@ Describe.writeOut = function(outs, json) {
 	}
 }
 
+Describe.createSample= function(m) {
+	var address = window.location.href;
+	address = address.substring(0,address.indexOf("/jest/"));
+	var address = address +"/"+ m.path;
+	if (m.pathParameters && m.pathParameters.length > 0) {
+		$.each(m.pathParameters, function(pi, p) {
+			address = address.replace('{' + p.name + '}', '替换参数'+pi);
+		});
+	}
+	if (m.queryParameters && m.queryParameters.length > 0) {
+		$.each(m.queryParameters, function(pi, p) {
+			var query = p.name + '=' + '替换参数'+pi;
+			if (address.indexOf("?") > 0) {
+				address += '&' + query;
+			} else {
+				address += '?' + query;
+			}
+		});
+	}
+	
+	var strSample="";
+	if (m.contentType.indexOf('application/json') > -1) {
+		  strSample =  "var data = {};" + "\n";
+			if (m.ins && m.ins.length > 0) {
+				$.each(m.ins, function(ii, i) {
+					switch (i.type) {
+					default:
+						if (i.isBaseType) {
+							if (i.isCollection) {
+								  strSample += 'data["'+i.name+'"] = ["参数1"];' + "\n";
+							} else {
+								  strSample += 'data["'+i.name+'"] = "参数";' + "\n";
+							}
+						} else {
+							      strSample += 'data["'+i.name+'"] = {"参数1":"value1","参数2":"value2"};'+"\n";
+						}
+					}
+				});
+			} else if (m.useJsonElementParameter) {
+				strSample += 'data = {"参数1":"value1","参数2":"value2"};' +"\n";
+			} else if (m.useStringParameter) {
+				strSample += 'data = "参数";'+"\n";
+			}
+			
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "dataType : 'json'" + ",\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : '"+m.contentType+ "',\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : data"+"\n";
+			strSample += "}).always(function(resultJson) {"+"\n";
+			strSample += "alert(JSON.stringify(resultJson, null, 4))" +"\n";
+			strSample += "});";
+			
+	} else {
+			strSample = "var formData = new FormData();" + "\n";
+			if (m.formParameters && m.formParameters.length > 0) {
+				$.each(m.formParameters, function(pi, p) {
+					if (p.type == "File") {
+							//formData.append(p.name, $('input[type=file]', '#formParameters')[0].files[0]);
+					strSample += 'formData.append("'+p.name+'", $("input[type=file]")[0].files[0]);' +  "\n";
+					} else {
+					strSample += 'formData.append("'+p.name+'", "参数'+pi+'");' +  "\n";
+					}
+				});
+			}
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : false,\n";
+			strSample += "processData  : false,\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : formData"+"\n";
+			strSample += "});";	
+	}
+
+	return  strSample;
+   }
+
 Describe.prototype = {
 	"load" : function() {
 		var str = '<ul>';
 		$.getJSON('../describe/describe.json?rd=' + Math.random(), function(json) {
 			$.each(json.jaxrs, function(ji, j) {
-				str += '<li>' + j.name;
+				str += '<li xtype="menu" >' + j.name;
 				$.each(j.methods, function(mi, m) {
-					str += '<ul><li><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
+					str += '<ul><li xtype="li"><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
 				});
 				str += '</li>'
 			});
@@ -182,6 +259,7 @@ Describe.prototype = {
 					$('#' + j.name + '_' + m.name).click(
 							function() {
 								$('#result').html('');
+								var sample = "";
 								var txt = '<fieldset id="method"><legend>Method</legend>';
 								txt += '<table>';
 								txt += '<tr><td>name:</td><td><a href="../describe/sources/' + m.className.replace(/\./g, '/') + '.java">' + m.name + '</a></td></tr>';
@@ -200,60 +278,63 @@ Describe.prototype = {
 											switch (p.name) {
 											case 'flag':
 											case 'id':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="(0)"/></td><td>' + p.name
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="(0)"/></td><td>' + p.name
 														+ ':' + p.description + '</td></tr>';
 												break;
 											case 'count':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="20"/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="20"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break;
 											default:
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break
 											}
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.formParameters && m.formParameters.length > 0) {
 									txt += '<fieldset id="formParameters"><legend>Form Parameter</legend>';
 									txt += '<table >';
 									$.each(m.formParameters, function(pi, p) {
 										if (p.type == "File") {
-											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>'
+											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>'
 													+ p.name + ':' + p.description + '</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.queryParameters && m.queryParameters.length > 0) {
 									txt += '<fieldset id="queryParameters"><legend>Query Parameter</legend>';
 									txt += '<table >';
 									$.each(m.queryParameters, function(pi, p) {
-										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':' + p.description
+										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':' + p.description
 												+ '</td></tr>';
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.ins && m.ins.length > 0) {
 									txt += '<fieldset id="ins"><legend>In</legend>';
 									txt += '<table>';
 									$.each(m.ins, function(ii, i) {
 										if (i.isCollection) {
-											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':' + i.description
+											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':' + i.description
 											'</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':'
+											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':'
 													+ i.description
 											'</td></tr>';
 										}
@@ -261,22 +342,26 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
+								
 								if (m.useJsonElementParameter) {
 									txt += '<fieldset><legend>JsonElement</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>json</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.useStringParameter) {
 									txt += '<fieldset><legend>String</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>string</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.outs && m.outs.length > 0) {
 									txt += '<fieldset id="outs"><legend>Out</legend>';
 									txt += '<table>';
@@ -287,7 +372,9 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								$('#content').html(txt);
+								
 								$('#' + m.name + '_' + m.type, '#method').click(function() {
 									var address = '../' + m.path;
 									if (m.pathParameters && m.pathParameters.length > 0) {
@@ -308,7 +395,6 @@ Describe.prototype = {
 									if (m.contentType.indexOf('application/json') > -1) {
 										switch (m.type) {
 										case 'POST':
-										debugger;
 											var data = {};
 											if (m.ins && m.ins.length > 0) {
 												$.each(m.ins, function(ii, i) {
@@ -321,21 +407,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -355,21 +431,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -385,6 +451,7 @@ Describe.prototype = {
 										default:
 											break;
 										}
+										
 									} else {
 										switch (m.type) {
 										case 'POST':
@@ -424,9 +491,31 @@ Describe.prototype = {
 										}
 									}
 								})
+								
+								debugger;
+							 $('#Sample').html(Describe.createSample(m));
 							});
 				});
 			});
+		 
+		  $("[xtype='menu']").click(
+				  function(event) {
+					    if(event.stopPropagation){
+						    event.stopPropagation();
+						  }else{
+						     event.cancelBubble = true;
+						  }
+					    $(this).children().toggle();
+					});
+		  $("[xtype='li']").click( function(event) {
+			    if(event.stopPropagation){
+				    event.stopPropagation();
+				  }else{
+				     event.cancelBubble = true;
+				  }
+			})
 		});
+		
+	
 	}
 }

+ 19 - 6
o2server/x_bbs_assemble_control/src/main/webapp/jest/index.html

@@ -81,21 +81,34 @@
 </script>
 </head>
 
-<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px">
+<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">
 	<table style="width: 1800px; margin: 0 auto">
 		<tr>
 			<td style="width: 350px;" valign="top">
 				<fieldset>
 					<legend>API Menu</legend>
-					<div id="menu" style="height: 850px; overflow: auto">&nbsp;</div>
+					<div id="menu" style="height: 850px; overflow: auto;">&nbsp;</div>
 				</fieldset>
 			</td>
-			<td valign="top">
-				<fieldset>
-					<legend>API Content</legend>
+			<td valign="top">			
+				<!--<fieldset>
+					<legend>Content</legend>
 					<div id="content"
 						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word">&nbsp;</div>
-				</fieldset>
+				</fieldset> -->
+				
+				<div id="content"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">&nbsp;</div>
+						
+			    <fieldset>
+					<legend>
+						Sample&nbsp;<a  id="btn_copy"  href="javascript:" data-clipboard-target="#Sample">copy</a>&nbsp;
+					</legend><div style="padding-left:12px">
+					<div id="Sample"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word; width: 1400px;">&nbsp;</div>
+						</div>
+				</fieldset>		
+						
 				<fieldset>
 					<legend>
 						Result&nbsp;<a id="btn_copy" href="javascript:" data-clipboard-target="#result">copy</a>&nbsp;

+ 18 - 0
o2server/x_bbs_core_entity/src/main/java/com/x/bbs/entity/BBSSubjectAttachment.java

@@ -12,6 +12,7 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.openjpa.persistence.jdbc.Index;
 
@@ -108,6 +109,16 @@ public class BBSSubjectAttachment extends StorageObject {
 		return str;
 	}
 
+	@Override
+	public Boolean getDeepPath() {
+		return BooleanUtils.isTrue(this.deepPath);
+	}
+
+	@Override
+	public void setDeepPath(Boolean deepPath) {
+		this.deepPath = deepPath;
+	}
+
 	/*
 	 * =========================================================================
 	 * ========= 以上为 JpaObject 默认字段
@@ -231,6 +242,13 @@ public class BBSSubjectAttachment extends StorageObject {
 	@CheckPersist(allowEmpty = false)
 	private String site;
 
+	public static final String deepPath_FIELDNAME = "deepPath";
+	@FieldDescribe("是否使用更深的路径.")
+	@CheckPersist(allowEmpty = true)
+	@Column(name = ColumnNamePrefix + deepPath_FIELDNAME)
+	@Index(name = TABLE + IndexNameMiddle + deepPath_FIELDNAME)
+	private Boolean deepPath;
+
 	public String getForumId() {
 		return forumId;
 	}

+ 1 - 0
o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/ApplicationServletContextListener.java

@@ -14,6 +14,7 @@ public class ApplicationServletContextListener implements ServletContextListener
 		try {
 			ThisApplication.context = Context.concrete(servletContextEvent);
 			ThisApplication.init();
+			ThisApplication.context().regist();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 1 - 1
o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/jaxrs/test/ActionTest1.java

@@ -18,7 +18,7 @@ public class ActionTest1 extends BaseAction {
 		ActionResult<Wo> result = new ActionResult<>();
 		Wo wo = new Wo();
 		wo.setValue(true);
-		ThisApplication.context().scheduleLocal(AlarmTrigger.class);
+		ThisApplication.context().scheduleLocal(AlarmTrigger.class,1);
 		result.setData(wo);
 		return result;
 	}

+ 3 - 3
o2server/x_calendar_assemble_control/src/main/java/com/x/calendar/assemble/control/schedule/AlarmTrigger.java

@@ -3,7 +3,6 @@ package com.x.calendar.assemble.control.schedule;
 import java.util.Date;
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
 import org.quartz.JobExecutionException;
 
@@ -11,6 +10,7 @@ import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.tools.ListTools;
 import com.x.calendar.assemble.control.Business;
 import com.x.calendar.assemble.control.factory.MessageFactory;
@@ -23,13 +23,13 @@ import com.x.calendar.core.entity.Calendar_Event;
  * @author O2LEE
  *
  */
-public class AlarmTrigger implements Job {
+public class AlarmTrigger extends AbstractJob {
 
 	private static Logger logger = LoggerFactory.getLogger(AlarmTrigger.class);
 	protected Calendar_EventServiceAdv calendar_EventServiceAdv = new Calendar_EventServiceAdv();
 
 	@Override
-	public void execute(JobExecutionContext arg0) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 			Business business = new Business(emc);
 			alarm(business);

+ 132 - 43
o2server/x_calendar_assemble_control/src/main/webapp/jest/describe.js

@@ -1,7 +1,6 @@
 var Describe = function() {
 	// 20180730
 }
-
 Describe.splitValue = function(str) {
 	if (str) {
 		if (str.length > 0) {
@@ -10,7 +9,6 @@ Describe.splitValue = function(str) {
 	}
 	return [];
 }
-
 Describe.joinValue = function(o, split) {
 	var s = ',';
 	if (split) {
@@ -23,7 +21,6 @@ Describe.joinValue = function(o, split) {
 	}
 	return o;
 }
-
 Describe.doPost = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -59,7 +56,6 @@ Describe.doPost = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doPut = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -95,7 +91,6 @@ Describe.doPut = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doGet = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -119,7 +114,6 @@ Describe.doGet = function(address, m) {
 		window.open(address, '_blank');
 	}
 }
-
 Describe.doDelete = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -155,7 +149,6 @@ Describe.doDelete = function(address, m) {
 		});
 	}
 }
-
 Describe.writeOut = function(outs, json) {
 	if (outs && (outs.length) && json && json.data) {
 		$.each(Object.keys(json.data), function(i, k) {
@@ -164,14 +157,98 @@ Describe.writeOut = function(outs, json) {
 	}
 }
 
+Describe.createSample= function(m) {
+	var address = window.location.href;
+	address = address.substring(0,address.indexOf("/jest/"));
+	var address = address +"/"+ m.path;
+	if (m.pathParameters && m.pathParameters.length > 0) {
+		$.each(m.pathParameters, function(pi, p) {
+			address = address.replace('{' + p.name + '}', '替换参数'+pi);
+		});
+	}
+	if (m.queryParameters && m.queryParameters.length > 0) {
+		$.each(m.queryParameters, function(pi, p) {
+			var query = p.name + '=' + '替换参数'+pi;
+			if (address.indexOf("?") > 0) {
+				address += '&' + query;
+			} else {
+				address += '?' + query;
+			}
+		});
+	}
+	
+	var strSample="";
+	if (m.contentType.indexOf('application/json') > -1) {
+		  strSample =  "var data = {};" + "\n";
+			if (m.ins && m.ins.length > 0) {
+				$.each(m.ins, function(ii, i) {
+					switch (i.type) {
+					default:
+						if (i.isBaseType) {
+							if (i.isCollection) {
+								  strSample += 'data["'+i.name+'"] = ["参数1"];' + "\n";
+							} else {
+								  strSample += 'data["'+i.name+'"] = "参数";' + "\n";
+							}
+						} else {
+							      strSample += 'data["'+i.name+'"] = {"参数1":"value1","参数2":"value2"};'+"\n";
+						}
+					}
+				});
+			} else if (m.useJsonElementParameter) {
+				strSample += 'data = {"参数1":"value1","参数2":"value2"};' +"\n";
+			} else if (m.useStringParameter) {
+				strSample += 'data = "参数";'+"\n";
+			}
+			
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "dataType : 'json'" + ",\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : '"+m.contentType+ "',\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : data"+"\n";
+			strSample += "}).always(function(resultJson) {"+"\n";
+			strSample += "alert(JSON.stringify(resultJson, null, 4))" +"\n";
+			strSample += "});";
+			
+	} else {
+			strSample = "var formData = new FormData();" + "\n";
+			if (m.formParameters && m.formParameters.length > 0) {
+				$.each(m.formParameters, function(pi, p) {
+					if (p.type == "File") {
+							//formData.append(p.name, $('input[type=file]', '#formParameters')[0].files[0]);
+					strSample += 'formData.append("'+p.name+'", $("input[type=file]")[0].files[0]);' +  "\n";
+					} else {
+					strSample += 'formData.append("'+p.name+'", "参数'+pi+'");' +  "\n";
+					}
+				});
+			}
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : false,\n";
+			strSample += "processData  : false,\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : formData"+"\n";
+			strSample += "});";	
+	}
+
+	return  strSample;
+   }
+
 Describe.prototype = {
 	"load" : function() {
 		var str = '<ul>';
 		$.getJSON('../describe/describe.json?rd=' + Math.random(), function(json) {
 			$.each(json.jaxrs, function(ji, j) {
-				str += '<li>' + j.name;
+				str += '<li xtype="menu" >' + j.name;
 				$.each(j.methods, function(mi, m) {
-					str += '<ul><li><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
+					str += '<ul><li xtype="li"><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
 				});
 				str += '</li>'
 			});
@@ -182,6 +259,7 @@ Describe.prototype = {
 					$('#' + j.name + '_' + m.name).click(
 							function() {
 								$('#result').html('');
+								var sample = "";
 								var txt = '<fieldset id="method"><legend>Method</legend>';
 								txt += '<table>';
 								txt += '<tr><td>name:</td><td><a href="../describe/sources/' + m.className.replace(/\./g, '/') + '.java">' + m.name + '</a></td></tr>';
@@ -200,60 +278,63 @@ Describe.prototype = {
 											switch (p.name) {
 											case 'flag':
 											case 'id':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="(0)"/></td><td>' + p.name
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="(0)"/></td><td>' + p.name
 														+ ':' + p.description + '</td></tr>';
 												break;
 											case 'count':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="20"/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="20"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break;
 											default:
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break
 											}
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.formParameters && m.formParameters.length > 0) {
 									txt += '<fieldset id="formParameters"><legend>Form Parameter</legend>';
 									txt += '<table >';
 									$.each(m.formParameters, function(pi, p) {
 										if (p.type == "File") {
-											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>'
+											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>'
 													+ p.name + ':' + p.description + '</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.queryParameters && m.queryParameters.length > 0) {
 									txt += '<fieldset id="queryParameters"><legend>Query Parameter</legend>';
 									txt += '<table >';
 									$.each(m.queryParameters, function(pi, p) {
-										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':' + p.description
+										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':' + p.description
 												+ '</td></tr>';
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.ins && m.ins.length > 0) {
 									txt += '<fieldset id="ins"><legend>In</legend>';
 									txt += '<table>';
 									$.each(m.ins, function(ii, i) {
 										if (i.isCollection) {
-											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':' + i.description
+											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':' + i.description
 											'</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':'
+											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':'
 													+ i.description
 											'</td></tr>';
 										}
@@ -261,22 +342,26 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
+								
 								if (m.useJsonElementParameter) {
 									txt += '<fieldset><legend>JsonElement</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>json</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.useStringParameter) {
 									txt += '<fieldset><legend>String</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>string</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.outs && m.outs.length > 0) {
 									txt += '<fieldset id="outs"><legend>Out</legend>';
 									txt += '<table>';
@@ -287,7 +372,9 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								$('#content').html(txt);
+								
 								$('#' + m.name + '_' + m.type, '#method').click(function() {
 									var address = '../' + m.path;
 									if (m.pathParameters && m.pathParameters.length > 0) {
@@ -308,7 +395,6 @@ Describe.prototype = {
 									if (m.contentType.indexOf('application/json') > -1) {
 										switch (m.type) {
 										case 'POST':
-										debugger;
 											var data = {};
 											if (m.ins && m.ins.length > 0) {
 												$.each(m.ins, function(ii, i) {
@@ -321,21 +407,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -355,21 +431,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -385,6 +451,7 @@ Describe.prototype = {
 										default:
 											break;
 										}
+										
 									} else {
 										switch (m.type) {
 										case 'POST':
@@ -424,9 +491,31 @@ Describe.prototype = {
 										}
 									}
 								})
+								
+								debugger;
+							 $('#Sample').html(Describe.createSample(m));
 							});
 				});
 			});
+		 
+		  $("[xtype='menu']").click(
+				  function(event) {
+					    if(event.stopPropagation){
+						    event.stopPropagation();
+						  }else{
+						     event.cancelBubble = true;
+						  }
+					    $(this).children().toggle();
+					});
+		  $("[xtype='li']").click( function(event) {
+			    if(event.stopPropagation){
+				    event.stopPropagation();
+				  }else{
+				     event.cancelBubble = true;
+				  }
+			})
 		});
+		
+	
 	}
 }

+ 19 - 6
o2server/x_calendar_assemble_control/src/main/webapp/jest/index.html

@@ -81,21 +81,34 @@
 </script>
 </head>
 
-<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px">
+<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">
 	<table style="width: 1800px; margin: 0 auto">
 		<tr>
 			<td style="width: 350px;" valign="top">
 				<fieldset>
 					<legend>API Menu</legend>
-					<div id="menu" style="height: 850px; overflow: auto">&nbsp;</div>
+					<div id="menu" style="height: 850px; overflow: auto;">&nbsp;</div>
 				</fieldset>
 			</td>
-			<td valign="top">
-				<fieldset>
-					<legend>API Content</legend>
+			<td valign="top">			
+				<!--<fieldset>
+					<legend>Content</legend>
 					<div id="content"
 						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word">&nbsp;</div>
-				</fieldset>
+				</fieldset> -->
+				
+				<div id="content"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">&nbsp;</div>
+						
+			    <fieldset>
+					<legend>
+						Sample&nbsp;<a  id="btn_copy"  href="javascript:" data-clipboard-target="#Sample">copy</a>&nbsp;
+					</legend><div style="padding-left:12px">
+					<div id="Sample"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word; width: 1400px;">&nbsp;</div>
+						</div>
+				</fieldset>		
+						
 				<fieldset>
 					<legend>
 						Result&nbsp;<a id="btn_copy" href="javascript:" data-clipboard-target="#result">copy</a>&nbsp;

+ 1 - 0
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/ApplicationServletContextListener.java

@@ -14,6 +14,7 @@ public class ApplicationServletContextListener implements ServletContextListener
 		try {
 			ThisApplication.context = Context.concrete(servletContextEvent);
 			ThisApplication.init();
+			ThisApplication.context().regist();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 2 - 2
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/ThisApplication.java

@@ -52,8 +52,8 @@ public class ThisApplication {
 		// 每天凌晨2点执行一次
 		context.schedule( Timertask_LogRecordCheckTask.class, "0 0 2 * * ?" );
 		context.schedule( Timertask_BatchOperationTask.class, "0 */5 * * * ?" );
-		cmsBatchOperationPersistService.initOperationRunning();
-		cmsBatchOperationPersistService.checkDocumentReviewStatus();
+		//cmsBatchOperationPersistService.initOperationRunning();
+		//cmsBatchOperationPersistService.checkDocumentReviewStatus();
 	}
 
 	public static void destroy() {

+ 9 - 4
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/jaxrs/appinfo/BaseAction.java

@@ -71,7 +71,7 @@ public class BaseAction extends StandardJaxrsAction {
 			if( ListTools.isNotEmpty( inAppInfoIds )) {
 				viewableAppInfoIds = inAppInfoIds; //可发布栏目就限制为inAppInfoIds
 			}else {
-				viewableAppInfoIds = appInfoServiceAdv.listAllIds(documentType); //所有栏目均可发布
+				viewableAppInfoIds = appInfoServiceAdv.listAllIds(documentType); //所有栏目均可
 			}
 			viewableCategoryIds = categoryInfoServiceAdv.listCategoryIdsWithAppIds( viewableAppInfoIds, documentType, manager, maxCount );
 		}else {
@@ -79,10 +79,15 @@ public class BaseAction extends StandardJaxrsAction {
 				unitNames = userManagerService.listUnitNamesWithPerson( personName );
 				groupNames = userManagerService.listGroupNamesByPerson( personName );
 			}
+			//查询用户可以访问到的栏目
+			viewableAppInfoIds = permissionQueryService.listViewableAppIdByPerson(personName, isAnonymous, unitNames, groupNames, inAppInfoIds, null, documentType, maxCount );
+			if( ListTools.isNotEmpty( viewableAppInfoIds )) {
+				viewableAppInfoIds.add("NO_APPINFO");
+			}
+			
 			//根据人员的发布权限获取可以发布文档的分类信息ID列表
-			viewableCategoryIds = permissionQueryService.listViewableCategoryIdByPerson( personName, isAnonymous, unitNames, groupNames, inAppInfoIds, 
+			viewableCategoryIds = permissionQueryService.listViewableCategoryIdByPerson( personName, isAnonymous, unitNames, groupNames, viewableAppInfoIds, 
 					null, null, documentType, maxCount, manager );
-			
 		}
 		return composeCategoriesIntoAppInfo( viewableAppInfoIds, viewableCategoryIds, appType );
 	}
@@ -122,7 +127,7 @@ public class BaseAction extends StandardJaxrsAction {
 			}
 			//2、根据人员的发布权限获取可以发布文档的分类信息ID列表
 			publishableCategoryIds = permissionQueryService.listPublishableCategoryIdByPerson(
-					personName, isAnonymous, unitNames, groupNames, inAppInfoIds, null, null, documentType, maxCount, manager );		
+					personName, isAnonymous, unitNames, groupNames, inAppInfoIds, null, null, documentType, maxCount, manager );
 		}
 //		if( ListTools.isNotEmpty(publishableCategoryIds  )) {
 //			System.out.println(">>>>>>>>>publishableCategoryIds.size=" + publishableCategoryIds.size() );

+ 10 - 4
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/service/ReviewService.java

@@ -640,15 +640,21 @@ public class ReviewService {
 		review.setCategoryId( document.getCategoryId() );
 		review.setCategoryName( document.getCategoryName() );
 		
-		review.setCreatorPerson( document.getCreatorPerson() );
-		review.setCreatorTopUnitName( document.getCreatorTopUnitName() );
-		review.setCreatorUnitName( document.getCreatorUnitName() );
-		
 		review.setCreateTime(  document.getCreateTime()  );
 		review.setDocCreateTime( document.getCreateTime() );	
 		review.setPublishTime(  document.getPublishTime()  );
 		review.setUpdateTime(  document.getUpdateTime()  );	
 		
+		review.setCreatorPerson( document.getCreatorPerson() );
+		review.setCreatorTopUnitName( document.getCreatorTopUnitName() );
+		review.setCreatorUnitName( document.getCreatorUnitName() );
+		
+		if(StringUtils.isEmpty( review.getCreatorPerson() )) {
+			review.setCreatorPerson( "xadmin" );
+			review.setCreatorTopUnitName( "xadmin" );
+			review.setCreatorUnitName( "xadmin" );
+		}
+		
 		review.setImportBatchName( document.getImportBatchName() );
 		
 		review.setPermissionObj( person );

+ 27 - 25
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/timertask/Timertask_BatchOperationTask.java

@@ -2,14 +2,13 @@ package com.x.cms.assemble.control.timertask;
 
 import java.util.List;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.x.base.core.container.EntityManagerContainer;
 import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.base.core.project.tools.ListTools;
 import com.x.cms.assemble.control.ThisApplication;
 import com.x.cms.assemble.control.service.CmsBatchOperationPersistService;
@@ -22,55 +21,58 @@ import com.x.cms.core.entity.CmsBatchOperation;
  * 定时代理: 定期执行批处理,将批处理信息压入队列(如果队列是空的话)
  *
  */
-public class Timertask_BatchOperationTask implements Job {
+public class Timertask_BatchOperationTask extends AbstractJob {
 
-	private static Logger logger = LoggerFactory.getLogger( Timertask_BatchOperationTask.class );
+	private static Logger logger = LoggerFactory.getLogger(Timertask_BatchOperationTask.class);
 	private CmsBatchOperationQueryService cmsBatchOperationQueryService = new CmsBatchOperationQueryService();
 
 	@Override
-	public void execute( JobExecutionContext arg0 ) throws JobExecutionException {
-		if( ThisApplication.queueBatchOperation.isEmpty() ) {
-			List<CmsBatchOperation> operations = null;		
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
+		if (ThisApplication.queueBatchOperation.isEmpty()) {
+			List<CmsBatchOperation> operations = null;
 			try {
 				logger.info("Timertask_BatchOperationTask ->  query 2000 cms batch operation in database......");
-				operations = cmsBatchOperationQueryService.list( 2000 );
+				operations = cmsBatchOperationQueryService.list(2000);
 			} catch (Exception e) {
 				logger.warn("Timertask_BatchOperationTask -> list operations got an exception.");
 				logger.error(e);
 			}
-			
-			if( ListTools.isNotEmpty( operations )) {
-				for( CmsBatchOperation operation : operations ) {
+
+			if (ListTools.isNotEmpty(operations)) {
+				for (CmsBatchOperation operation : operations) {
 					try {
-						logger.info("Timertask_BatchOperationTask -> send operation to queue[queueBatchOperation]......");
-						ThisApplication.queueBatchOperation.send( operation );
+						logger.info(
+								"Timertask_BatchOperationTask -> send operation to queue[queueBatchOperation]......");
+						ThisApplication.queueBatchOperation.send(operation);
 					} catch (Exception e) {
 						logger.warn("Timertask_BatchOperationTask -> send operation to queue got an exception.");
 						logger.error(e);
 					}
 				}
-			}else {
-				logger.info("Timertask_BatchOperationTask -> not fount any cms batch operation, try to check unreview document in database......");
-				//如果队列里已经没有任务了,那么检查一下是否还有未revieiw的文档,添加到队列
-				DocumentInfoService documentInfoService = new DocumentInfoService();				
+			} else {
+				logger.info(
+						"Timertask_BatchOperationTask -> not fount any cms batch operation, try to check unreview document in database......");
+				// 如果队列里已经没有任务了,那么检查一下是否还有未revieiw的文档,添加到队列
+				DocumentInfoService documentInfoService = new DocumentInfoService();
 				try (EntityManagerContainer emc = EntityManagerContainerFactory.instance().create()) {
 					List<String> ids = documentInfoService.listUnReviewIds(emc, 5000);
-					if( ListTools.isNotEmpty( ids )) {
+					if (ListTools.isNotEmpty(ids)) {
 						CmsBatchOperationPersistService cmsBatchOperationPersistService = new CmsBatchOperationPersistService();
-						for( String docId : ids ) {
-							cmsBatchOperationPersistService.addOperation( 
-									CmsBatchOperationProcessService.OPT_OBJ_DOCUMENT, 
-									CmsBatchOperationProcessService.OPT_TYPE_PERMISSION,  docId,  docId, "刷新文档权限:ID=" +  docId );
+						for (String docId : ids) {
+							cmsBatchOperationPersistService.addOperation(
+									CmsBatchOperationProcessService.OPT_OBJ_DOCUMENT,
+									CmsBatchOperationProcessService.OPT_TYPE_PERMISSION, docId, docId,
+									"刷新文档权限:ID=" + docId);
 						}
-					}else {
+					} else {
 						logger.info("Timertask_BatchOperationTask -> not found any unreview document in database.");
-						//也没有需要review的文档了,那么检查一下最近变更过的身份,组织,群组,人员等信息
+						// 也没有需要review的文档了,那么检查一下最近变更过的身份,组织,群组,人员等信息
 					}
 				} catch (Exception e) {
 					e.printStackTrace();
 				}
 			}
-		}else {
+		} else {
 			logger.info("Timertask_BatchOperationTask -> queueBatchOperation is processing, wait to next excute.");
 		}
 		logger.info("Timertask_BatchOperationTask -> batch operations timer task excute completed.");

+ 3 - 4
o2server/x_cms_assemble_control/src/main/java/com/x/cms/assemble/control/timertask/Timertask_LogRecordCheckTask.java

@@ -1,11 +1,10 @@
 package com.x.cms.assemble.control.timertask;
 
-import org.quartz.Job;
 import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
 
 import com.x.base.core.project.logger.Logger;
 import com.x.base.core.project.logger.LoggerFactory;
+import com.x.base.core.project.schedule.AbstractJob;
 import com.x.cms.assemble.control.service.DocumentViewRecordServiceAdv;
 import com.x.cms.assemble.control.service.LogService;
 
@@ -15,7 +14,7 @@ import com.x.cms.assemble.control.service.LogService;
  * @author O2LEE
  *
  */
-public class Timertask_LogRecordCheckTask implements Job {
+public class Timertask_LogRecordCheckTask extends AbstractJob {
 
 	private static Logger logger = LoggerFactory.getLogger(Timertask_LogRecordCheckTask.class);
 	private LogService logService = new LogService();
@@ -26,7 +25,7 @@ public class Timertask_LogRecordCheckTask implements Job {
 	private Integer stay_count_viewRecord = 100000; // 保留100,000条
 
 	@Override
-	public void execute(JobExecutionContext arg0) throws JobExecutionException {
+	public void schedule(JobExecutionContext jobExecutionContext) throws Exception {
 		try {
 			logService.clean(stay_yearnum_operationLog, stay_count_operationLog);
 			logger.info("Timertask_LogRecordCheckTask -> clean operation logs excute success. stay_yearnum:" + stay_yearnum_operationLog + ",stay_count:" + stay_count_operationLog);

+ 132 - 43
o2server/x_cms_assemble_control/src/main/webapp/jest/describe.js

@@ -1,7 +1,6 @@
 var Describe = function() {
 	// 20180730
 }
-
 Describe.splitValue = function(str) {
 	if (str) {
 		if (str.length > 0) {
@@ -10,7 +9,6 @@ Describe.splitValue = function(str) {
 	}
 	return [];
 }
-
 Describe.joinValue = function(o, split) {
 	var s = ',';
 	if (split) {
@@ -23,7 +21,6 @@ Describe.joinValue = function(o, split) {
 	}
 	return o;
 }
-
 Describe.doPost = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -59,7 +56,6 @@ Describe.doPost = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doPut = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -95,7 +91,6 @@ Describe.doPut = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doGet = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -119,7 +114,6 @@ Describe.doGet = function(address, m) {
 		window.open(address, '_blank');
 	}
 }
-
 Describe.doDelete = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -155,7 +149,6 @@ Describe.doDelete = function(address, m) {
 		});
 	}
 }
-
 Describe.writeOut = function(outs, json) {
 	if (outs && (outs.length) && json && json.data) {
 		$.each(Object.keys(json.data), function(i, k) {
@@ -164,14 +157,98 @@ Describe.writeOut = function(outs, json) {
 	}
 }
 
+Describe.createSample= function(m) {
+	var address = window.location.href;
+	address = address.substring(0,address.indexOf("/jest/"));
+	var address = address +"/"+ m.path;
+	if (m.pathParameters && m.pathParameters.length > 0) {
+		$.each(m.pathParameters, function(pi, p) {
+			address = address.replace('{' + p.name + '}', '替换参数'+pi);
+		});
+	}
+	if (m.queryParameters && m.queryParameters.length > 0) {
+		$.each(m.queryParameters, function(pi, p) {
+			var query = p.name + '=' + '替换参数'+pi;
+			if (address.indexOf("?") > 0) {
+				address += '&' + query;
+			} else {
+				address += '?' + query;
+			}
+		});
+	}
+	
+	var strSample="";
+	if (m.contentType.indexOf('application/json') > -1) {
+		  strSample =  "var data = {};" + "\n";
+			if (m.ins && m.ins.length > 0) {
+				$.each(m.ins, function(ii, i) {
+					switch (i.type) {
+					default:
+						if (i.isBaseType) {
+							if (i.isCollection) {
+								  strSample += 'data["'+i.name+'"] = ["参数1"];' + "\n";
+							} else {
+								  strSample += 'data["'+i.name+'"] = "参数";' + "\n";
+							}
+						} else {
+							      strSample += 'data["'+i.name+'"] = {"参数1":"value1","参数2":"value2"};'+"\n";
+						}
+					}
+				});
+			} else if (m.useJsonElementParameter) {
+				strSample += 'data = {"参数1":"value1","参数2":"value2"};' +"\n";
+			} else if (m.useStringParameter) {
+				strSample += 'data = "参数";'+"\n";
+			}
+			
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "dataType : 'json'" + ",\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : '"+m.contentType+ "',\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : data"+"\n";
+			strSample += "}).always(function(resultJson) {"+"\n";
+			strSample += "alert(JSON.stringify(resultJson, null, 4))" +"\n";
+			strSample += "});";
+			
+	} else {
+			strSample = "var formData = new FormData();" + "\n";
+			if (m.formParameters && m.formParameters.length > 0) {
+				$.each(m.formParameters, function(pi, p) {
+					if (p.type == "File") {
+							//formData.append(p.name, $('input[type=file]', '#formParameters')[0].files[0]);
+					strSample += 'formData.append("'+p.name+'", $("input[type=file]")[0].files[0]);' +  "\n";
+					} else {
+					strSample += 'formData.append("'+p.name+'", "参数'+pi+'");' +  "\n";
+					}
+				});
+			}
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : false,\n";
+			strSample += "processData  : false,\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : formData"+"\n";
+			strSample += "});";	
+	}
+
+	return  strSample;
+   }
+
 Describe.prototype = {
 	"load" : function() {
 		var str = '<ul>';
 		$.getJSON('../describe/describe.json?rd=' + Math.random(), function(json) {
 			$.each(json.jaxrs, function(ji, j) {
-				str += '<li>' + j.name;
+				str += '<li xtype="menu" >' + j.name;
 				$.each(j.methods, function(mi, m) {
-					str += '<ul><li><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
+					str += '<ul><li xtype="li"><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
 				});
 				str += '</li>'
 			});
@@ -182,6 +259,7 @@ Describe.prototype = {
 					$('#' + j.name + '_' + m.name).click(
 							function() {
 								$('#result').html('');
+								var sample = "";
 								var txt = '<fieldset id="method"><legend>Method</legend>';
 								txt += '<table>';
 								txt += '<tr><td>name:</td><td><a href="../describe/sources/' + m.className.replace(/\./g, '/') + '.java">' + m.name + '</a></td></tr>';
@@ -200,60 +278,63 @@ Describe.prototype = {
 											switch (p.name) {
 											case 'flag':
 											case 'id':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="(0)"/></td><td>' + p.name
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="(0)"/></td><td>' + p.name
 														+ ':' + p.description + '</td></tr>';
 												break;
 											case 'count':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="20"/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="20"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break;
 											default:
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break
 											}
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.formParameters && m.formParameters.length > 0) {
 									txt += '<fieldset id="formParameters"><legend>Form Parameter</legend>';
 									txt += '<table >';
 									$.each(m.formParameters, function(pi, p) {
 										if (p.type == "File") {
-											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>'
+											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>'
 													+ p.name + ':' + p.description + '</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.queryParameters && m.queryParameters.length > 0) {
 									txt += '<fieldset id="queryParameters"><legend>Query Parameter</legend>';
 									txt += '<table >';
 									$.each(m.queryParameters, function(pi, p) {
-										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':' + p.description
+										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':' + p.description
 												+ '</td></tr>';
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.ins && m.ins.length > 0) {
 									txt += '<fieldset id="ins"><legend>In</legend>';
 									txt += '<table>';
 									$.each(m.ins, function(ii, i) {
 										if (i.isCollection) {
-											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':' + i.description
+											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':' + i.description
 											'</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':'
+											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':'
 													+ i.description
 											'</td></tr>';
 										}
@@ -261,22 +342,26 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
+								
 								if (m.useJsonElementParameter) {
 									txt += '<fieldset><legend>JsonElement</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>json</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.useStringParameter) {
 									txt += '<fieldset><legend>String</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>string</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.outs && m.outs.length > 0) {
 									txt += '<fieldset id="outs"><legend>Out</legend>';
 									txt += '<table>';
@@ -287,7 +372,9 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								$('#content').html(txt);
+								
 								$('#' + m.name + '_' + m.type, '#method').click(function() {
 									var address = '../' + m.path;
 									if (m.pathParameters && m.pathParameters.length > 0) {
@@ -308,7 +395,6 @@ Describe.prototype = {
 									if (m.contentType.indexOf('application/json') > -1) {
 										switch (m.type) {
 										case 'POST':
-										debugger;
 											var data = {};
 											if (m.ins && m.ins.length > 0) {
 												$.each(m.ins, function(ii, i) {
@@ -321,21 +407,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -355,21 +431,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -385,6 +451,7 @@ Describe.prototype = {
 										default:
 											break;
 										}
+										
 									} else {
 										switch (m.type) {
 										case 'POST':
@@ -424,9 +491,31 @@ Describe.prototype = {
 										}
 									}
 								})
+								
+								debugger;
+							 $('#Sample').html(Describe.createSample(m));
 							});
 				});
 			});
+		 
+		  $("[xtype='menu']").click(
+				  function(event) {
+					    if(event.stopPropagation){
+						    event.stopPropagation();
+						  }else{
+						     event.cancelBubble = true;
+						  }
+					    $(this).children().toggle();
+					});
+		  $("[xtype='li']").click( function(event) {
+			    if(event.stopPropagation){
+				    event.stopPropagation();
+				  }else{
+				     event.cancelBubble = true;
+				  }
+			})
 		});
+		
+	
 	}
 }

+ 19 - 6
o2server/x_cms_assemble_control/src/main/webapp/jest/index.html

@@ -81,21 +81,34 @@
 </script>
 </head>
 
-<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px">
+<body style="font-size: 12px; font-family: Microsoft Yahei; margin: 0px;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">
 	<table style="width: 1800px; margin: 0 auto">
 		<tr>
 			<td style="width: 350px;" valign="top">
 				<fieldset>
 					<legend>API Menu</legend>
-					<div id="menu" style="height: 850px; overflow: auto">&nbsp;</div>
+					<div id="menu" style="height: 850px; overflow: auto;">&nbsp;</div>
 				</fieldset>
 			</td>
-			<td valign="top">
-				<fieldset>
-					<legend>API Content</legend>
+			<td valign="top">			
+				<!--<fieldset>
+					<legend>Content</legend>
 					<div id="content"
 						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word">&nbsp;</div>
-				</fieldset>
+				</fieldset> -->
+				
+				<div id="content"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word;border-image: linear-gradient(#ffffff, #e7e7e7 15%, #e7e7e7 100%, #ffffff);box-shadow: inset 15px 0 5px -16px #e7e7e7;background-image: -webkit-radial-gradient(right, #f2f2f2, #ffffff 100%);">&nbsp;</div>
+						
+			    <fieldset>
+					<legend>
+						Sample&nbsp;<a  id="btn_copy"  href="javascript:" data-clipboard-target="#Sample">copy</a>&nbsp;
+					</legend><div style="padding-left:12px">
+					<div id="Sample"
+						style="white-space: pre; font-size: 12px; word-break: break-all; word-wrap: break-word; width: 1400px;">&nbsp;</div>
+						</div>
+				</fieldset>		
+						
 				<fieldset>
 					<legend>
 						Result&nbsp;<a id="btn_copy" href="javascript:" data-clipboard-target="#result">copy</a>&nbsp;

+ 34 - 13
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/FileInfo.java

@@ -17,6 +17,7 @@ import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.persistence.UniqueConstraint;
 
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.openjpa.persistence.PersistentCollection;
 import org.apache.openjpa.persistence.jdbc.ContainerTable;
@@ -72,7 +73,7 @@ public class FileInfo extends StorageObject {
 	public static final String lastUpdateTime_FIELDNAME = "lastUpdateTime";
 	@FieldDescribe("最后更新时间")
 	@Temporal(TemporalType.TIMESTAMP)
-	@Column( name = ColumnNamePrefix + lastUpdateTime_FIELDNAME)
+	@Column(name = ColumnNamePrefix + lastUpdateTime_FIELDNAME)
 	@Index(name = TABLE + IndexNameMiddle + lastUpdateTime_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private Date lastUpdateTime;
@@ -110,18 +111,28 @@ public class FileInfo extends StorageObject {
 		this.storage = storage;
 	}
 
+	@Override
+	public Boolean getDeepPath() {
+		return BooleanUtils.isTrue(this.deepPath);
+	}
+
+	@Override
+	public void setDeepPath(Boolean deepPath) {
+		this.deepPath = deepPath;
+	}
+
 	@Override
 	public String path() throws Exception {
-		if ( StringUtils.isEmpty(  this.appId )) {
+		if (StringUtils.isEmpty(this.appId)) {
 			throw new Exception("appId can not be null.");
 		}
-		if ( StringUtils.isEmpty( this.categoryId )) {
+		if (StringUtils.isEmpty(this.categoryId)) {
 			throw new Exception("categoryId can not be null.");
 		}
-		if (StringUtils.isEmpty( documentId)) {
+		if (StringUtils.isEmpty(documentId)) {
 			throw new Exception("documentId can not be null.");
 		}
-		if (StringUtils.isEmpty( id )) {
+		if (StringUtils.isEmpty(id)) {
 			throw new Exception("id can not be empty.");
 		}
 		String str = DateTools.format(this.getCreateTime(), DateTools.formatCompact_yyyyMMdd);
@@ -151,7 +162,8 @@ public class FileInfo extends StorageObject {
 	 */
 	public static final String name_FIELDNAME = "name";
 	@FieldDescribe("文件真实名称")
-	@Column(length = AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix + name_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix
+			+ name_FIELDNAME)
 	@CheckPersist(fileNameString = true, allowEmpty = true)
 	private String name;
 
@@ -163,7 +175,8 @@ public class FileInfo extends StorageObject {
 
 	public static final String fileName_FIELDNAME = "fileName";
 	@FieldDescribe("服务器上编码后的文件名,为了方便辨识带扩展名")
-	@Column(length = AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix + fileName_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix
+			+ fileName_FIELDNAME)
 	@CheckPersist(fileNameString = true, allowEmpty = true)
 	private String fileName;
 
@@ -197,7 +210,7 @@ public class FileInfo extends StorageObject {
 	@Column(length = JpaObject.length_16B, name = ColumnNamePrefix + fileExtType_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String fileExtType;
-	
+
 	public static final String type_FIELDNAME = "type";
 	@FieldDescribe("根据流文件判断的文件类型.")
 	@Column(length = JpaObject.length_255B, name = ColumnNamePrefix + type_FIELDNAME)
@@ -223,7 +236,8 @@ public class FileInfo extends StorageObject {
 
 	public static final String creatorUid_FIELDNAME = "creatorUid";
 	@FieldDescribe("创建者UID")
-	@Column(length =AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix + creatorUid_FIELDNAME)
+	@Column(length = AbstractPersistenceProperties.processPlatform_name_length, name = ColumnNamePrefix
+			+ creatorUid_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String creatorUid;
 
@@ -235,17 +249,17 @@ public class FileInfo extends StorageObject {
 
 	public static final String seqNumber_FIELDNAME = "seqNumber";
 	@FieldDescribe("排序号")
-	@Column( name = ColumnNamePrefix + seqNumber_FIELDNAME)
+	@Column(name = ColumnNamePrefix + seqNumber_FIELDNAME)
 	@CheckPersist(fileNameString = true, allowEmpty = true)
 	private Integer seqNumber = 1000;
 
 	public static final String length_FIELDNAME = "length";
 	@FieldDescribe("文件大小.")
-	@Column( name = ColumnNamePrefix + length_FIELDNAME)
+	@Column(name = ColumnNamePrefix + length_FIELDNAME)
 	@Index(name = TABLE + "_length")
 	@CheckPersist(allowEmpty = true)
 	private Long length;
-	
+
 	public static final String text_FIELDNAME = "text";
 	@FieldDescribe("文本.")
 	@Lob
@@ -253,7 +267,7 @@ public class FileInfo extends StorageObject {
 	@Column(length = JpaObject.length_100M, name = ColumnNamePrefix + text_FIELDNAME)
 	@CheckPersist(allowEmpty = true)
 	private String text;
-	
+
 	public static final String readIdentityList_FIELDNAME = "readIdentityList";
 	@FieldDescribe("可以访问的身份.")
 	@PersistentCollection(fetch = FetchType.EAGER)
@@ -324,6 +338,13 @@ public class FileInfo extends StorageObject {
 	@CheckPersist(allowEmpty = true)
 	private List<String> controllerUnitList;
 
+	public static final String deepPath_FIELDNAME = "deepPath";
+	@FieldDescribe("是否使用更深的路径.")
+	@CheckPersist(allowEmpty = true)
+	@Column(name = ColumnNamePrefix + deepPath_FIELDNAME)
+	@Index(name = TABLE + IndexNameMiddle + deepPath_FIELDNAME)
+	private Boolean deepPath;
+
 	/**
 	 * 获取文件所属应用ID
 	 * 

+ 3 - 3
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/CalculateEntryTools.java

@@ -117,21 +117,21 @@ public class CalculateEntryTools {
 		Map<Object, Long> map = new LinkedHashMap<Object, Long>();
 		if ((null != groupEntry) && (groupEntry.available())) {
 			map = table.stream()
-					.collect(Collectors.groupingBy(row -> row.get(groupEntry.getColumn()), Collectors.counting()));
+					.collect(Collectors.groupingBy(row -> row.find(groupEntry.getColumn()), Collectors.counting()));
 		}
 		return map;
 	}
 
 	private static Map<Object, Double> groupSum(Table table, CalculateEntry calculateEntry, GroupEntry groupEntry)
 			throws Exception {
-		Map<Object, Double> map = table.stream().collect(Collectors.groupingBy(row -> row.get(groupEntry.getColumn()),
+		Map<Object, Double> map = table.stream().collect(Collectors.groupingBy(row -> row.find(groupEntry.getColumn()),
 				Collectors.summingDouble(row -> row.getAsDouble(calculateEntry.getColumn()))));
 		return map;
 	}
 
 	private static Map<Object, Double> groupAverage(List<Row> rows, CalculateEntry calculateEntry,
 			GroupEntry groupEntry) throws Exception {
-		Map<Object, Double> map = rows.stream().collect(Collectors.groupingBy(row -> row.get(groupEntry.getColumn()),
+		Map<Object, Double> map = rows.stream().collect(Collectors.groupingBy(row -> row.find(groupEntry.getColumn()),
 				Collectors.averagingDouble(row -> row.getAsDouble(calculateEntry.getColumn()))));
 		return map;
 	}

+ 1 - 1
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/GroupEntryTools.java

@@ -14,7 +14,7 @@ public class GroupEntryTools {
 	public static List<LinkedHashMap<String, Object>> group(Table table, GroupEntry groupEntry,
 			List<OrderEntry> orderEntries) throws Exception {
 		Map<Object, List<Row>> map = table.stream()
-				.collect(Collectors.groupingBy(row -> row.get(groupEntry.getColumn())));
+				.collect(Collectors.groupingBy(row -> row.find(groupEntry.getColumn())));
 		List<LinkedHashMap<String, Object>> result = new ArrayList<>();
 
 		for (Entry<Object, List<Row>> en : map.entrySet()) {

+ 2 - 2
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/OrderEntryTools.java

@@ -29,9 +29,9 @@ public class OrderEntryTools {
 		CompareToBuilder compareToBuilder = new CompareToBuilder();
 		for (OrderEntry en : orderEntries) {
 			if (Objects.equals(OrderType.asc, en.getOrderType())) {
-				compareToBuilder.append(o1.get(en.getColumn()), o2.get(en.getColumn()));
+				compareToBuilder.append(o1.find(en.getColumn()), o2.find(en.getColumn()));
 			} else {
-				compareToBuilder.append(o2.get(en.getColumn()), o1.get(en.getColumn()));
+				compareToBuilder.append(o2.find(en.getColumn()), o1.find(en.getColumn()));
 			}
 		}
 		return compareToBuilder.toComparison();

+ 1 - 1
o2server/x_cms_core_entity/src/main/java/com/x/cms/core/entity/query/Row.java

@@ -37,7 +37,7 @@ public class Row extends GsonPropertyObject {
 		return data;
 	}
 
-	public Object get(String key) {
+	public Object find(String key) {
 		return this.data.get(key);
 	}
 

+ 17 - 19
o2server/x_cms_core_express/src/main/java/com/x/cms/core/express/permission/CmsPermissionService.java

@@ -54,8 +54,6 @@ public class CmsPermissionService {
 		// Predicate p=null;
 		Predicate p = CriteriaBuilderTools.composePredicateWithQueryFilter(Review_.class, cb, null, root, queryFilter);
 		cq.orderBy(cb.desc(root.get(Review.publishTime_FIELDNAME)));
-		// System.out.println(">>>>>>>>>>>SQL:" + em.createQuery( cq.where( p )
-		// ).setMaxResults( maxResultCount ).toString() );
 		reviews = em.createQuery(cq.where(p)).setMaxResults(maxResultCount).getResultList();
 		if (reviews != null && !reviews.isEmpty()) {
 			for (Review review : reviews) {
@@ -332,10 +330,10 @@ public class CmsPermissionService {
 
 		if (!isAnonymous) {
 			// 在指定的栏目范围内(inAppInfoIds),查询所有我可以发布文档的分类ID列表(包含有发布权限的分类,不检测全员可发布标识)
-			publishableCategoryInfoIds = addResultToSourceList(
-					this.listPublishableCategoryIdsInPermission(emc, personName, unitNames, groupNames, inAppInfoIds,
-							inCategoryInfoIds, excludCategoryInfoIds, documentType, maxCount),
-					publishableCategoryInfoIds);
+//			publishableCategoryInfoIds = addResultToSourceList(
+//					this.listPublishableCategoryIdsInPermission(emc, personName, unitNames, groupNames, inAppInfoIds,
+//							inCategoryInfoIds, excludCategoryInfoIds, documentType, maxCount),
+//					publishableCategoryInfoIds);
 
 			// 在指定的栏目范围内(inAppInfoIds),查询我可以管理的分类ID列表
 			publishableCategoryInfoIds = addResultToSourceList(this.listManageableCategoryIdsByPerson(emc, personName,
@@ -528,20 +526,20 @@ public class CmsPermissionService {
 					cb.isMember(personName, root.get(CategoryInfo.viewablePersonList_FIELDNAME)));
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					cb.isMember(personName, root.get(CategoryInfo.manageablePersonList_FIELDNAME)));
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					cb.isMember(personName, root.get(CategoryInfo.publishablePersonList_FIELDNAME)));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					cb.isMember(personName, root.get(CategoryInfo.publishablePersonList_FIELDNAME)));
 		}
 		if (ListTools.isNotEmpty(unitNames)) {
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					root.get(CategoryInfo.publishableUnitList_FIELDNAME).in(unitNames));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					root.get(CategoryInfo.publishableUnitList_FIELDNAME).in(unitNames));
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					root.get(CategoryInfo.viewableUnitList_FIELDNAME).in(unitNames));
 		}
 		if (ListTools.isNotEmpty(groupNames)) {
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					root.get(CategoryInfo.publishableGroupList_FIELDNAME).in(groupNames));
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					root.get(CategoryInfo.viewableGroupList_FIELDNAME).in(groupNames));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					root.get(CategoryInfo.viewableGroupList_FIELDNAME).in(groupNames));
 		}
 
 		p = CriteriaBuilderTools.predicate_and(cb, p, p_permission);
@@ -616,20 +614,20 @@ public class CmsPermissionService {
 			// 可以管理的栏目,肯定可以发布信息
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					cb.isMember(personName, root.get(AppInfo.manageablePersonList_FIELDNAME)));
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					cb.isMember(personName, root.get(AppInfo.publishablePersonList_FIELDNAME)));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					cb.isMember(personName, root.get(AppInfo.publishablePersonList_FIELDNAME)));
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					cb.isMember(personName, root.get(AppInfo.viewablePersonList_FIELDNAME)));
 		}
 		if (ListTools.isNotEmpty(unitNames)) {
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					root.get(AppInfo.publishableUnitList_FIELDNAME).in(unitNames));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					root.get(AppInfo.publishableUnitList_FIELDNAME).in(unitNames));
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					root.get(AppInfo.viewableUnitList_FIELDNAME).in(unitNames));
 		}
 		if (ListTools.isNotEmpty(groupNames)) {
-			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
-					root.get(AppInfo.publishableGroupList_FIELDNAME).in(groupNames));
+//			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
+//					root.get(AppInfo.publishableGroupList_FIELDNAME).in(groupNames));
 			p_permission = CriteriaBuilderTools.predicate_or(cb, p_permission,
 					root.get(AppInfo.viewableGroupList_FIELDNAME).in(groupNames));
 		}
@@ -806,7 +804,7 @@ public class CmsPermissionService {
 					cb.equal(root.get(AppInfo.documentType_FIELDNAME), documentType));
 		}
 		Predicate permission = cb.isTrue(root.get(AppInfo.allPeopleView_FIELDNAME));
-		permission = cb.or(permission, cb.isTrue(root.get(AppInfo.allPeoplePublish_FIELDNAME)));
+//		permission = cb.or(permission, cb.isTrue(root.get(AppInfo.allPeoplePublish_FIELDNAME)));
 
 		p = CriteriaBuilderTools.predicate_and(cb, p, permission);
 		appInfoIds = em.createQuery(cq.where(p)).getResultList();

+ 1 - 0
o2server/x_component_assemble_control/src/main/java/com/x/component/assemble/control/ApplicationServletContextListener.java

@@ -14,6 +14,7 @@ public class ApplicationServletContextListener implements ServletContextListener
 		try {
 			ThisApplication.context = Context.concrete(servletContextEvent);
 			ThisApplication.init();
+			ThisApplication.context().regist();
 		} catch (Exception e) {
 			e.printStackTrace();
 		}

+ 132 - 43
o2server/x_component_assemble_control/src/main/webapp/jest/describe.js

@@ -1,7 +1,6 @@
 var Describe = function() {
 	// 20180730
 }
-
 Describe.splitValue = function(str) {
 	if (str) {
 		if (str.length > 0) {
@@ -10,7 +9,6 @@ Describe.splitValue = function(str) {
 	}
 	return [];
 }
-
 Describe.joinValue = function(o, split) {
 	var s = ',';
 	if (split) {
@@ -23,7 +21,6 @@ Describe.joinValue = function(o, split) {
 	}
 	return o;
 }
-
 Describe.doPost = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -59,7 +56,6 @@ Describe.doPost = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doPut = function(address, m, data) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -95,7 +91,6 @@ Describe.doPut = function(address, m, data) {
 		});
 	}
 }
-
 Describe.doGet = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -119,7 +114,6 @@ Describe.doGet = function(address, m) {
 		window.open(address, '_blank');
 	}
 }
-
 Describe.doDelete = function(address, m) {
 	$('#url').html(address);
 	if ((m.resultContentType) && m.resultContentType.indexOf('application/json') > -1) {
@@ -155,7 +149,6 @@ Describe.doDelete = function(address, m) {
 		});
 	}
 }
-
 Describe.writeOut = function(outs, json) {
 	if (outs && (outs.length) && json && json.data) {
 		$.each(Object.keys(json.data), function(i, k) {
@@ -164,14 +157,98 @@ Describe.writeOut = function(outs, json) {
 	}
 }
 
+Describe.createSample= function(m) {
+	var address = window.location.href;
+	address = address.substring(0,address.indexOf("/jest/"));
+	var address = address +"/"+ m.path;
+	if (m.pathParameters && m.pathParameters.length > 0) {
+		$.each(m.pathParameters, function(pi, p) {
+			address = address.replace('{' + p.name + '}', '替换参数'+pi);
+		});
+	}
+	if (m.queryParameters && m.queryParameters.length > 0) {
+		$.each(m.queryParameters, function(pi, p) {
+			var query = p.name + '=' + '替换参数'+pi;
+			if (address.indexOf("?") > 0) {
+				address += '&' + query;
+			} else {
+				address += '?' + query;
+			}
+		});
+	}
+	
+	var strSample="";
+	if (m.contentType.indexOf('application/json') > -1) {
+		  strSample =  "var data = {};" + "\n";
+			if (m.ins && m.ins.length > 0) {
+				$.each(m.ins, function(ii, i) {
+					switch (i.type) {
+					default:
+						if (i.isBaseType) {
+							if (i.isCollection) {
+								  strSample += 'data["'+i.name+'"] = ["参数1"];' + "\n";
+							} else {
+								  strSample += 'data["'+i.name+'"] = "参数";' + "\n";
+							}
+						} else {
+							      strSample += 'data["'+i.name+'"] = {"参数1":"value1","参数2":"value2"};'+"\n";
+						}
+					}
+				});
+			} else if (m.useJsonElementParameter) {
+				strSample += 'data = {"参数1":"value1","参数2":"value2"};' +"\n";
+			} else if (m.useStringParameter) {
+				strSample += 'data = "参数";'+"\n";
+			}
+			
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "dataType : 'json'" + ",\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : '"+m.contentType+ "',\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : data"+"\n";
+			strSample += "}).always(function(resultJson) {"+"\n";
+			strSample += "alert(JSON.stringify(resultJson, null, 4))" +"\n";
+			strSample += "});";
+			
+	} else {
+			strSample = "var formData = new FormData();" + "\n";
+			if (m.formParameters && m.formParameters.length > 0) {
+				$.each(m.formParameters, function(pi, p) {
+					if (p.type == "File") {
+							//formData.append(p.name, $('input[type=file]', '#formParameters')[0].files[0]);
+					strSample += 'formData.append("'+p.name+'", $("input[type=file]")[0].files[0]);' +  "\n";
+					} else {
+					strSample += 'formData.append("'+p.name+'", "参数'+pi+'");' +  "\n";
+					}
+				});
+			}
+			strSample += "$.ajax({" + "\n";
+			strSample += "type : '"+ m.type + "',\n";
+			strSample += "url : '"+address + "',\n";
+			strSample += "headers : {'x-debugger' : true}" + ",\n";
+			strSample += "contentType : false,\n";
+			strSample += "processData  : false,\n";
+			strSample += "xhrFields : {'withCredentials' : true}" + ",\n";
+			strSample += "crossDomain : true"+ ",\n";
+			strSample += "data : formData"+"\n";
+			strSample += "});";	
+	}
+
+	return  strSample;
+   }
+
 Describe.prototype = {
 	"load" : function() {
 		var str = '<ul>';
 		$.getJSON('../describe/describe.json?rd=' + Math.random(), function(json) {
 			$.each(json.jaxrs, function(ji, j) {
-				str += '<li>' + j.name;
+				str += '<li xtype="menu" >' + j.name;
 				$.each(j.methods, function(mi, m) {
-					str += '<ul><li><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
+					str += '<ul><li xtype="li"><a id ="' + j.name + '_' + m.name + '" href="#">' + m.name + '</a></li></ul>';
 				});
 				str += '</li>'
 			});
@@ -182,6 +259,7 @@ Describe.prototype = {
 					$('#' + j.name + '_' + m.name).click(
 							function() {
 								$('#result').html('');
+								var sample = "";
 								var txt = '<fieldset id="method"><legend>Method</legend>';
 								txt += '<table>';
 								txt += '<tr><td>name:</td><td><a href="../describe/sources/' + m.className.replace(/\./g, '/') + '.java">' + m.name + '</a></td></tr>';
@@ -200,60 +278,63 @@ Describe.prototype = {
 											switch (p.name) {
 											case 'flag':
 											case 'id':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="(0)"/></td><td>' + p.name
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="(0)"/></td><td>' + p.name
 														+ ':' + p.description + '</td></tr>';
 												break;
 											case 'count':
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; " value="20"/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid" value="20"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break;
 											default:
-												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+												txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 														+ p.description + '</td></tr>';
 												break
 											}
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.formParameters && m.formParameters.length > 0) {
 									txt += '<fieldset id="formParameters"><legend>Form Parameter</legend>';
 									txt += '<table >';
 									$.each(m.formParameters, function(pi, p) {
 										if (p.type == "File") {
-											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>'
+											txt += '<tr><td><input type="file" name="' + p.name + '" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>'
 													+ p.name + ':' + p.description + '</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':'
+											txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':'
 													+ p.description + '</td></tr>';
 										}
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.queryParameters && m.queryParameters.length > 0) {
 									txt += '<fieldset id="queryParameters"><legend>Query Parameter</legend>';
 									txt += '<table >';
 									$.each(m.queryParameters, function(pi, p) {
-										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; "/></td><td>' + p.name + ':' + p.description
+										txt += '<tr><td><input type="text" id="' + p.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + p.name + ':' + p.description
 												+ '</td></tr>';
 									});
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.ins && m.ins.length > 0) {
 									txt += '<fieldset id="ins"><legend>In</legend>';
 									txt += '<table>';
 									$.each(m.ins, function(ii, i) {
 										if (i.isCollection) {
-											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':' + i.description
+											txt += '<tr><td><textarea id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':' + i.description
 											'</td></tr>';
 										} else {
-											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; "/></td><td>' + i.name + ':'
+											txt += '<tr><td><input type="text" id="' + i.name + '" style="width:600px; padding:1px; border:1px #000000 solid"/></td><td>' + i.name + ':'
 													+ i.description
 											'</td></tr>';
 										}
@@ -261,22 +342,26 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
+								
 								if (m.useJsonElementParameter) {
 									txt += '<fieldset><legend>JsonElement</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="jsonElement" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>json</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.useStringParameter) {
 									txt += '<fieldset><legend>String</legend>';
 									txt += '<table><tr><td>';
-									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; "/>';
+									txt += '<textarea id="string" style="height:300px; width:600px; padding:1px; border:1px #000000 solid"/>';
 									txt += '</td><td>string</td></tr>';
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								if (m.outs && m.outs.length > 0) {
 									txt += '<fieldset id="outs"><legend>Out</legend>';
 									txt += '<table>';
@@ -287,7 +372,9 @@ Describe.prototype = {
 									txt += '</table>';
 									txt += '</fieldset>';
 								}
+								
 								$('#content').html(txt);
+								
 								$('#' + m.name + '_' + m.type, '#method').click(function() {
 									var address = '../' + m.path;
 									if (m.pathParameters && m.pathParameters.length > 0) {
@@ -308,7 +395,6 @@ Describe.prototype = {
 									if (m.contentType.indexOf('application/json') > -1) {
 										switch (m.type) {
 										case 'POST':
-										debugger;
 											var data = {};
 											if (m.ins && m.ins.length > 0) {
 												$.each(m.ins, function(ii, i) {
@@ -321,21 +407,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -355,21 +431,11 @@ Describe.prototype = {
 																data[i.name] = $('#' + i.name, '#ins').val();
 															}
 														} else {
-															if (i.isCollection) {
-																data[i.name] = Describe.splitValue($('#' + i.name, '#ins').val());
-															} else {
-																if( $('#' + i.name, '#ins').val() == null || typeof($('#' + i.name, '#ins').val()) == "undefind" || $('#' + i.name, '#ins').val() == "" ){
-																	$('#' + i.name, '#ins').val("{}");
-																}
-																data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
-															}
+															data[i.name] = $.parseJSON($('#' + i.name, '#ins').val());
 														}
 													}
 												});
 											} else if (m.useJsonElementParameter) {
-												if( $('#jsonElement').val() == null || typeof($('#jsonElement').val()) == "undefind" || $('#jsonElement').val() == "" ){
-													$('#jsonElement').val("{}");
-												}
 												data = $.parseJSON($('#jsonElement').val());
 											} else if (m.useStringParameter) {
 												data = $('#string').val();
@@ -385,6 +451,7 @@ Describe.prototype = {
 										default:
 											break;
 										}
+										
 									} else {
 										switch (m.type) {
 										case 'POST':
@@ -424,9 +491,31 @@ Describe.prototype = {
 										}
 									}
 								})
+								
+								debugger;
+							 $('#Sample').html(Describe.createSample(m));
 							});
 				});
 			});
+		 
+		  $("[xtype='menu']").click(
+				  function(event) {
+					    if(event.stopPropagation){
+						    event.stopPropagation();
+						  }else{
+						     event.cancelBubble = true;
+						  }
+					    $(this).children().toggle();
+					});
+		  $("[xtype='li']").click( function(event) {
+			    if(event.stopPropagation){
+				    event.stopPropagation();
+				  }else{
+				     event.cancelBubble = true;
+				  }
+			})
 		});
+		
+	
 	}
 }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff