Browse Source

git-svn-id: https://192.168.57.71/svn/jsgkj@1054 931142cf-59ea-a443-aa0e-51397b428577

xt_yuanxd 8 years ago
parent
commit
5063d294d8
100 changed files with 9332 additions and 0 deletions
  1. 26 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/.classpath
  2. 23 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/.project
  3. 3 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.core.resources.prefs
  4. 5 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.jdt.core.prefs
  5. 4 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.m2e.core.prefs
  6. 26 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/pom.xml
  7. 60 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/BizLog.java
  8. 10 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/Logical.java
  9. 17 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresAuthentication.java
  10. 17 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresGuest.java
  11. 31 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresPermissions.java
  12. 31 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresRoles.java
  13. 16 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresUser.java
  14. 38 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/ctl/BaseCtl.java
  15. 109 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/ctl/WebJsonResult.java
  16. 11 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/dao/BaseDao.java
  17. 18 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/entity/Entity.java
  18. 39 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/service/BaseService.java
  19. 283 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/vo/NodeVo.java
  20. 109 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/code/entity/Code.java
  21. 69 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/code/service/CodeService.java
  22. 154 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/data/entity/DataPerm.java
  23. 87 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/data/service/DataPermService.java
  24. 47 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/exception/BizException.java
  25. 195 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/job/entity/JobInfo.java
  26. 98 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/job/service/JobInfoService.java
  27. 50 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/log/BizLogRecorder.java
  28. 107 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/entity/Function.java
  29. 158 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/entity/Menu.java
  30. 246 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/service/MenuService.java
  31. 105 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/org/entity/Org.java
  32. 80 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/org/service/OrgService.java
  33. 94 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/role/entity/Role.java
  34. 106 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/role/service/RoleService.java
  35. 124 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/SecurityMgr.java
  36. 8 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/SessionMgr.java
  37. 14 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/WorkFlowMgr.java
  38. 14 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/aware/SecurityMgrAware.java
  39. 11 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/aware/WorkflowMgrAware.java
  40. 153 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/user/entity/User.java
  41. 97 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/user/service/UserService.java
  42. 548 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/Assert.java
  43. 24 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/CoreConstants.java
  44. 58 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/SystemParam.java
  45. 50 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/WorkflowConsts.java
  46. 170 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/Execution.java
  47. 72 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/NextTask.java
  48. 192 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/ProcessDefinitionInfo.java
  49. 63 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/ProcessInst.java
  50. 161 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/StepNode.java
  51. 220 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/SubmitInfo.java
  52. 196 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/TaskNode.java
  53. 213 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WFStartInfo.java
  54. 66 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WfResult.java
  55. 406 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WorkFlowEngineClient.java
  56. 375 0
      gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WorkItem.java
  57. 26 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/.classpath
  58. 23 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/.project
  59. 2 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.core.resources.prefs
  60. 5 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.jdt.core.prefs
  61. 4 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.m2e.core.prefs
  62. 13 0
      gkoa/trunk/xtframe-oa/modules/xtframe-io/pom.xml
  63. 31 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/.classpath
  64. 29 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/.project
  65. 5 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.core.resources.prefs
  66. 5 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.jdt.core.prefs
  67. 4 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.m2e.core.prefs
  68. 109 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/pom.xml
  69. 1 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/readme
  70. 87 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/dao/CodeDao.java
  71. 185 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/entity/CodeEntity.java
  72. 65 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/service/impl/CodeServiceImpl.java
  73. 21 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/BaseEntity.java
  74. 43 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/BaseSecurityService.java
  75. 97 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/CaptchaFormAuthenticationFilter.java
  76. 15 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/MyOracleDialect.java
  77. 22 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/OracleSqlConsts.java
  78. 90 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/QueryService.java
  79. 44 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepository.java
  80. 64 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepositoryFactory.java
  81. 16 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepositoryFactoryBean.java
  82. 48 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SimplePageRequest.java
  83. 166 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SimpleSecRepository.java
  84. 104 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SystemAuthenticationListener.java
  85. 91 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SystemParamEntity.java
  86. 50 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/dao/DataPermDao.java
  87. 153 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/entity/DataPermEntity.java
  88. 85 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/service/impl/DataPermServiceImpl.java
  89. 14 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/dao/JobInfoDao.java
  90. 174 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/entity/JobInfoEntity.java
  91. 82 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/impl/CommonJobListener.java
  92. 258 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/impl/JobInfoServiceImpl.java
  93. 13 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/dao/BizLogDao.java
  94. 275 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/entity/BizLogEntity.java
  95. 301 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/service/impl/SpringMvcBizLogRecorder.java
  96. 16 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/dao/FunctionDao.java
  97. 54 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/dao/MenuDao.java
  98. 112 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/entity/FunctionEntity.java
  99. 218 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/entity/MenuEntity.java
  100. 405 0
      gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/service/impl/MenuServiceImpl.java

+ 26 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/.classpath

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

+ 23 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/.project

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>xtCore-oa</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

+ 3 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/<project>=UTF-8

+ 5 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7

+ 4 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/.settings/org.eclipse.m2e.core.prefs

@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

+ 26 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/pom.xml

@@ -0,0 +1,26 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.xtframe</groupId>
+		<artifactId>xtproject-oa</artifactId>
+		<version>0.1.3-SNAPSHOT</version>
+		<relativePath>../../</relativePath>
+	</parent>
+	<artifactId>xtCore-oa</artifactId>
+	<name>新通开发框架核心</name>
+	<properties>
+		<spring.version>4.1.2.RELEASE</spring.version>
+		<jdk.version>1.7</jdk.version>
+		<jetty.version>7.6.8.v20121106</jetty.version>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<hibernate.version>4.3.7.Final</hibernate.version>
+	</properties>
+	<dependencies>
+		<dependency>
+			<groupId>com.xtframe</groupId>
+			<artifactId>xtutil-oa</artifactId>
+		</dependency>
+	</dependencies>
+	<description>提供框架核心定义</description>
+</project>

+ 60 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/BizLog.java

@@ -0,0 +1,60 @@
+package com.xtframe.core.anon;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 业务日志记录注解<br>
+ * 注解在需要进行业务日志控制的类或者方法上
+ * 
+ * @author 袁晓冬
+ * 
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface BizLog {
+    /** 定义日志类型 */
+    public enum LogType {
+        /** 登录 */
+        LOGIN("登录"),
+        /** 登出 */
+        LOGOUT("登出"),
+        /** 新增 */
+        ADD("新增"),
+        /** 编辑 */
+        EDIT("编辑"),
+        /** 删除 */
+        DELETE("删除"),
+        /** 查询 */
+        QUERY("查询"),
+        /** 上传 */
+        UPLOAD("上传"),
+        /** 下载 */
+        DOWNLOAD("下载"),
+        /** 打印 */
+        PRINT("打印"),
+        /** 统计 */
+        STATISTICS("统计"),
+        /** 其他 */
+        OTHER("其他");
+        private String value;
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        private LogType(String value) {
+            this.value = value;
+        }
+    };
+
+    LogType value() default LogType.ADD;
+}

+ 10 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/Logical.java

@@ -0,0 +1,10 @@
+package com.xtframe.core.anon.auth;
+
+/**
+ * 权限中用到的逻辑运算
+ * @author 袁晓冬
+ *
+ */
+public enum Logical {
+    AND, OR
+}

+ 17 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresAuthentication.java

@@ -0,0 +1,17 @@
+package com.xtframe.core.anon.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 认证用户才可访问
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresAuthentication {
+}

+ 17 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresGuest.java

@@ -0,0 +1,17 @@
+package com.xtframe.core.anon.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 游客才可访问
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresGuest {
+}

+ 31 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresPermissions.java

@@ -0,0 +1,31 @@
+package com.xtframe.core.anon.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 需要拥有指定权限才可访问
+ * 
+ * @author 袁晓冬
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresPermissions {
+
+    /**
+     * 一个活多个可访问权限
+     * 
+     * @return
+     */
+    String[] value();
+
+    /**
+     * 权限之前的逻辑关系,“与”{@link Logical#AND} 或者“或”{@link Logical#OR}
+     * 
+     * @return
+     */
+    Logical logical() default Logical.AND;
+
+}

+ 31 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresRoles.java

@@ -0,0 +1,31 @@
+package com.xtframe.core.anon.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 需要拥有指定的角色进行访问
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresRoles {
+
+    /**
+     * 一个或多个角色编码
+     * 
+     * @return
+     */
+    String[] value();
+
+    /**
+     * 逻辑关系,“与”{@link Logical#AND} 或者“或”{@link Logical#OR}
+     * 
+     * @return
+     */
+    Logical logical() default Logical.AND;
+}

+ 16 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/anon/auth/RequiresUser.java

@@ -0,0 +1,16 @@
+package com.xtframe.core.anon.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 需要登录后访问
+ * @author 袁晓冬
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresUser {
+}

+ 38 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/ctl/BaseCtl.java

@@ -0,0 +1,38 @@
+package com.xtframe.core.base.ctl;
+
+/**
+ * 控制器层基类
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class BaseCtl {
+
+    /** 新增记录ID标识 */
+    public static final String BLANK_UUID = "00";
+
+    /**
+     * 返回执行成功对象
+     * 
+     * @return
+     */
+    protected WebJsonResult success() {
+        WebJsonResult jsonResult = new WebJsonResult();
+        jsonResult.setSuccess(true);
+        return jsonResult;
+    }
+
+    /**
+     * 返回执行失败对象,并附带失败信息
+     * 
+     * @param msg
+     * @return
+     */
+    protected WebJsonResult error(String msg) {
+        WebJsonResult jsonResult = new WebJsonResult();
+        jsonResult.setSuccess(false);
+        jsonResult.setMessage(msg);
+        return jsonResult;
+    }
+
+}

+ 109 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/ctl/WebJsonResult.java

@@ -0,0 +1,109 @@
+package com.xtframe.core.base.ctl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 后台向前台传递的结果集<br>
+ * <p>
+ * 包含结果和消息两部分
+ * <p>
+ * 此对象仅用于controller层,其他层不要使用
+ * 
+ * @author 袁晓冬
+ * 
+ */
+public class WebJsonResult implements Serializable {
+
+	/** serialVersionUID */
+	private static final long serialVersionUID = -4396170415938706672L;
+
+	// 操作是否成功
+	private boolean success = true;
+	// 异常信息
+	private String message;
+
+	// 如果有多个结果,使用此属性
+	private Map<String, Object> attrs = new HashMap<String, Object>();
+
+	/**
+	 * 根据属性名称查询属性值
+	 * 
+	 * @param name
+	 *            属性名称
+	 * @return Object 属性值
+	 */
+	public Object getAttr(String name) {
+		return attrs.get(name);
+	}
+
+	/**
+	 * 获取返回结果属性
+	 * 
+	 * @return Map<String, Object>
+	 */
+	public Map<String, Object> getAttrs() {
+		return attrs;
+	}
+
+	/**
+	 * 获取执行结果返回消息
+	 * 
+	 * @return String
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/**
+	 * 执行是否成功
+	 * 
+	 * @return
+	 */
+	public boolean isSuccess() {
+		return success;
+	}
+
+	/**
+	 * 设置返回结果属性
+	 * 
+	 * @param name
+	 *            属性名称
+	 * @param value
+	 *            属性值
+	 */
+	public void setAttr(String name, Object value) {
+		attrs.put(name, value);
+	}
+
+	/**
+	 * 设置返回结果属性,覆盖原有所有属性
+	 * 
+	 * @param attrs
+	 *            Map<String, Object>
+	 */
+	public void setAttrs(Map<String, Object> attrs) {
+		this.attrs = attrs;
+	}
+
+	/**
+	 * 设置执行结果返回消息
+	 * 
+	 * @param message
+	 *            String
+	 */
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	/**
+	 * 设置执行是否成功
+	 * 
+	 * @param success
+	 *            boolean 执行结果
+	 */
+	public void setSuccess(boolean success) {
+		this.success = success;
+	}
+}

+ 11 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/dao/BaseDao.java

@@ -0,0 +1,11 @@
+package com.xtframe.core.base.dao;
+
+/**
+ * 数据库层基类
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class BaseDao {
+
+}

+ 18 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/entity/Entity.java

@@ -0,0 +1,18 @@
+package com.xtframe.core.base.entity;
+
+import java.io.Serializable;
+
+/**
+ * Entity基类
+ * 
+ * @author 袁晓冬
+ *
+ * @param <ID>
+ */
+
+public abstract class Entity<ID extends Serializable> implements Serializable {
+
+	/** serialVersionUID */
+	private static final long serialVersionUID = -6673000649753054544L;
+
+}

+ 39 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/service/BaseService.java

@@ -0,0 +1,39 @@
+package com.xtframe.core.base.service;
+
+import java.util.Map;
+
+/**
+ * 服务层基类
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class BaseService {
+
+	/** 可用Beans集合 */
+	protected Map<Object, Object> beans;
+
+	/**
+	 * 获取service可用Bean集合
+	 * 
+	 * @return Map<Object, Object>
+	 */
+	public Map<Object, Object> getBeans() {
+		return beans;
+	}
+
+	/**
+	 * 设置service可用Bean集合,一般由框架自动设置
+	 * 
+	 * @param beans
+	 */
+	public void setBeans(Map<Object, Object> beans) {
+		this.beans = beans;
+	}
+
+	/**
+	 * 初始化,一般用于服务中引用Bean的初始化
+	 */
+	public void init() {
+	};
+}

+ 283 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/base/vo/NodeVo.java

@@ -0,0 +1,283 @@
+/** 
+ * 文 件 名 : NodeVo.java 
+ * 创 建 人:袁晓冬
+ * 日     期: 2015年6月26日下午3:23:03
+ * 修 改 人: 
+ * 日     期: 
+ * 版 本 号: 
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司
+ */
+package com.xtframe.core.base.vo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司
+ * 项 目 名: xtCore-oa
+ * 注 释: 树图节点对象 <br/>
+ * 命名空间: com.xtframe.core.base.vo
+ * 创 建 人: 袁晓冬
+ * 日 期: 2015年6月26日下午3:23:03
+ * 修 改 人:
+ * 日 期:
+ * 修改原因:
+ * 版 本 号:
+ * 
+ * @since JDK 1.6
+ */
+public class NodeVo implements Cloneable, Comparable<NodeVo> {
+    /** 节点ID */
+    protected String id;
+    /** 上级节点 */
+    protected String parent;
+    /** 节点名称 */
+    protected String text;
+    /** 是否选中 */
+    protected boolean checked;
+    /** 节点图标样式 */
+    protected String iconCls;
+    /** 状态:打开/关闭 */
+    protected String state;
+    /** 节点属性信息 */
+    protected Map<String, String> attributes;
+    /** 下级节点 */
+    protected List<NodeVo> children;
+    /** 排序号 */
+    private int sortno;
+
+    /**
+     * 树图节点对象
+     */
+    public NodeVo() {
+
+    }
+
+    /**
+     * 树图节点对象
+     * 
+     * @param id
+     *            节点ID
+     * @param text
+     *            节点名称
+     * @param checked
+     *            是否选中
+     * @param iconCls
+     *            节点图标样式
+     * @param state
+     *            状态:打开/关闭
+     * @param attributes
+     *            节点属性信息
+     */
+    public NodeVo(String id, String text, boolean checked, String iconCls, String state, Map<String, String> attributes) {
+        super();
+        this.id = id;
+        this.text = text;
+        this.checked = checked;
+        this.iconCls = iconCls;
+        this.state = state;
+        this.attributes = attributes;
+    }
+
+    @Override
+    public NodeVo clone() throws CloneNotSupportedException {
+        return (NodeVo) super.clone();
+    }
+
+    @Override
+    public int compareTo(NodeVo o) {
+        return this.sortno - o.sortno;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        NodeVo other = (NodeVo) obj;
+        if (id == null) {
+            if (other.id != null) return false;
+        }
+        else if (!id.equals(other.id)) return false;
+        return true;
+    }
+
+    /**
+     * 获取节点属性
+     * 
+     * @return Map<String, String>
+     */
+    public Map<String, String> getAttributes() {
+        return attributes;
+    }
+
+    /**
+     * 获取下级节点列表
+     * 
+     * @return List<NodeVo>
+     */
+    public List<NodeVo> getChildren() {
+        return children;
+    }
+
+    /**
+     * 获取节点图标样式
+     * 
+     * @return String
+     */
+    public String getIconCls() {
+        return iconCls;
+    }
+
+    /**
+     * 获取节点ID
+     * 
+     * @return String
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * 获取上级ID
+     * 
+     * @return String
+     */
+    public String getParent() {
+        return parent;
+    }
+
+    /**
+     * 排序号
+     * 
+     * @return
+     */
+    public int getSortno() {
+        return sortno;
+    }
+
+    /**
+     * 获取节点状态
+     * 
+     * @return String
+     */
+    public String getState() {
+        return state;
+    }
+
+    /**
+     * 获取节点显示文本
+     * 
+     * @return String
+     */
+    public String getText() {
+        return text;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        return result;
+    }
+
+    /**
+     * 是否选中
+     * 
+     * @return boolean
+     */
+    public boolean isChecked() {
+        return checked;
+    }
+
+    /**
+     * 设置节点属性
+     * 
+     * @param attributes
+     *            Map<String, String>
+     */
+    public void setAttributes(Map<String, String> attributes) {
+        this.attributes = attributes;
+    }
+
+    /**
+     * 设置节点选中状态
+     * 
+     * @param checked
+     *            boolean
+     */
+    public void setChecked(boolean checked) {
+        this.checked = checked;
+    }
+
+    /**
+     * 设置下级节点
+     * 
+     * @param children
+     *            List<NodeVo>
+     */
+    public void setChildren(List<NodeVo> children) {
+        this.children = children;
+    }
+
+    /**
+     * 设置节点显示图标样式<br>
+     * 引用icons.css中的式样
+     * 
+     * @param iconCls
+     *            String
+     */
+    public void setIconCls(String iconCls) {
+        this.iconCls = iconCls;
+    }
+
+    /**
+     * 设置节点ID
+     * 
+     * @param id
+     *            String
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * 设置上级节点ID
+     * 
+     * @param parent
+     *            String
+     */
+    public void setParent(String parent) {
+        this.parent = parent;
+    }
+
+    /**
+     * 排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno) {
+        this.sortno = sortno;
+    }
+
+    /**
+     * 设置节点状态
+     * 
+     * @param state
+     *            String
+     */
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    /**
+     * 设置节点显示文本
+     * 
+     * @param text
+     *            String
+     */
+    public void setText(String text) {
+        this.text = text;
+    }
+}

+ 109 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/code/entity/Code.java

@@ -0,0 +1,109 @@
+package com.xtframe.core.code.entity;
+
+/**
+ * 字典表对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface Code {
+
+    /**
+     * 字典编码
+     * 
+     * @return
+     */
+    public String getCode();
+
+    /**
+     * 唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 是否末级节点
+     * 
+     * @return
+     */
+    public Boolean getLeaf();
+
+    /**
+     * 上级编码
+     * 
+     * @return
+     */
+    public String getPcode();
+
+    /**
+     * 上级唯一标识
+     * 
+     * @return
+     */
+    public String getPid();
+
+    /**
+     * 显示文本
+     * 
+     * @return
+     */
+    public String getText();
+
+    /**
+     * 是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 设置编码
+     * 
+     * @param code
+     */
+    public void setCode(String code);
+
+    /**
+     * 设置唯一标识
+     * 
+     * @param id
+     */
+    public void setId(String id);
+
+    /**
+     * 设置是否末级
+     * 
+     * @param leaf
+     */
+    public void setLeaf(Boolean leaf);
+
+    /**
+     * 设置上级编码
+     * 
+     * @param pcode
+     */
+    public void setPcode(String pcode);
+
+    /**
+     * 设置上级唯一标识
+     * 
+     * @param pid
+     */
+    public void setPid(String pid);
+
+    /**
+     * 设置显示文本
+     * 
+     * @param text
+     */
+    public void setText(String text);
+
+    /**
+     * 设置是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+
+}

+ 69 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/code/service/CodeService.java

@@ -0,0 +1,69 @@
+package com.xtframe.core.code.service;
+
+import java.util.List;
+
+import com.xtframe.core.code.entity.Code;
+
+/**
+ * 字典维护服务
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface CodeService {
+    /**
+     * 根据上级编码查找下级
+     * 
+     * @param pcode
+     * @return
+     */
+    public List<Code> findByPcode(String pcode);
+
+    /**
+     * 根据上级编码ID查找下级
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Code> findByPid(String pid);
+
+    /**
+     * 根据上级编码ID查找下级有效记录
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Code> findValidCodesByPid(String pid);
+
+    /**
+     * 根据主键查找
+     * 
+     * @param id
+     * @return
+     */
+    public Code findOne(String id);
+
+    /**
+     * 根据编码查找
+     * 
+     * @param id
+     * @return
+     */
+    public Code findByCode(String code);
+
+    /**
+     * 字典保存
+     * 
+     * @param code
+     * @return
+     */
+    public Code save(Code code);
+
+    /**
+     * 根据主键删除记录
+     * 
+     * @param ids
+     * @return
+     */
+    public String delete(String... ids);
+}

+ 154 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/data/entity/DataPerm.java

@@ -0,0 +1,154 @@
+package com.xtframe.core.data.entity;
+
+/**
+ * 数据权限实体
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface DataPerm {
+
+    /**
+     * 业务主键ID
+     * 
+     * @return
+     */
+    public abstract String getBusskey();
+
+    /**
+     * 数据分类
+     * 
+     * @return
+     */
+    public abstract String getDataType();
+
+    /**
+     * 记录唯一标识
+     * 
+     * @return
+     */
+    public abstract String getId();
+
+    /**
+     * 操作权限
+     * 
+     * @return
+     */
+    public String getOper();
+
+    /**
+     * 所属角色编码
+     * 
+     * @return
+     */
+    public String getRoleCode();
+
+    /**
+     * 字段1
+     * @return
+     */
+    public String getText1();
+
+    /**
+     * 字段2
+     * @return
+     */
+    public String getText2();
+
+    /**
+     * 字段3
+     * @return
+     */
+    public String getText3();
+
+    /**
+     * 字段4
+     * @return
+     */
+    public String getText4();
+
+    /**
+     * 字段5
+     * @return
+     */
+    public String getText5();
+
+    /**
+     * 所属用户ID
+     * 
+     * @return
+     */
+    public String getUserId();
+
+    /**
+     * 业务主键ID
+     * 
+     * @param busskey
+     */
+    public abstract void setBusskey(String busskey);
+
+    /**
+     * 数据分类
+     * 
+     * @param dataType
+     */
+    public abstract void setDataType(String dataType);
+
+    /**
+     * 记录唯一标识
+     * 
+     * @param id
+     */
+    public abstract void setId(String id);
+
+    /**
+     * 操作权限
+     * 
+     * @param oper
+     */
+    public void setOper(String oper);
+
+    /**
+     * 所属角色编码
+     * 
+     * @param roleCode
+     */
+    public void setRoleCode(String roleCode);
+
+    /**
+     * 字段1
+     * @param text1
+     */
+    public void setText1(String text1);
+
+    /**
+     * 字段2
+     * @param text2
+     */
+    public void setText2(String text2);
+
+    /**
+     * 字段3
+     * @param text3
+     */
+    public void setText3(String text3);
+
+    /**
+     * 字段4
+     * @param text4
+     */
+    public void setText4(String text4);
+
+    /**
+     * 字段5
+     * @param text5
+     */
+    public void setText5(String text5);
+
+    /**
+     * 所属用户ID
+     * 
+     * @param userId
+     */
+    public void setUserId(String userId);
+}

+ 87 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/data/service/DataPermService.java

@@ -0,0 +1,87 @@
+package com.xtframe.core.data.service;
+
+import java.util.List;
+
+import com.xtframe.core.data.entity.DataPerm;
+
+/**
+ * 数据权限服务接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface DataPermService {
+    /**
+     * 根据业务主键和角色编码查询操作权限,当权限为空时返回空字符串,当权限不存在时返回null
+     * 
+     * @param busskey
+     *            业务主键
+     * @param roleCode
+     *            角色编码
+     * @return oper 权限操作
+     * @see com.xtframe.core.data.entity.DataPerm#getOper()
+     */
+    String checkRolePermission(String busskey, String role);
+
+    /**
+     * 根据业务主键和用户ID查询操作权限,当权限为空时返回空字符串,当权限不存在时返回null
+     * 
+     * @param busskey
+     *            业务主键
+     * @param userid
+     *            用户ID
+     * @return oper 权限操作
+     * @see com.xtframe.core.data.entity.DataPerm#getOper()
+     */
+    String checkUserPermission(String busskey, String user);
+
+    /**
+     * 根据主键删除记录
+     * 
+     * @param ids
+     * @return
+     */
+    public String delete(String... ids);
+
+    /**
+     * 根据业务主键检索
+     * 
+     * @param busskey
+     * @return
+     */
+    public List<DataPerm> findByBusskey(String busskey);
+
+    /**
+     * 根据业务主键和数据类型检索
+     * 
+     * @param busskey
+     * @param dataType
+     * @return
+     */
+    public List<DataPerm> findByBusskeyAndDataType(String busskey, String dataType);
+
+    /**
+     * 根据业务主键和用户ID查询权限
+     * 
+     * @param busskey
+     * @param user
+     * @return
+     */
+    public List<DataPerm> findByBusskeyAndUserId(String busskey, String userId);
+
+    /**
+     * 根据主键查找实体
+     * 
+     * @param id
+     * @return
+     */
+    public DataPerm findOne(String id);
+
+    /**
+     * 保存实体
+     * 
+     * @param u
+     * @return
+     */
+    public DataPerm save(DataPerm dp);
+}

+ 47 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/exception/BizException.java

@@ -0,0 +1,47 @@
+package com.xtframe.core.exception;
+
+/**
+ * business exception's base class
+ * 
+ * 
+ */
+public class BizException extends RuntimeException {
+	private static final long serialVersionUID = 3358078457294620782L;
+
+	/**
+	 * Constructs a new exception with the specified detail message. The cause
+	 * is not initialized, and may subsequently be initialized by a call to
+	 * {@link #initCause}.
+	 * 
+	 * @param message
+	 *            the detail message. The detail message is saved for later
+	 *            retrieval by the {@link #getMessage()} method.
+	 */
+	public BizException(String message) {
+		super(message);
+	}
+
+	/**
+	 * Constructs a new exception with the specified detail message and cause.
+	 * <p>
+	 * Note that the detail message associated with <code>cause</code> is
+	 * <i>not</i> automatically incorporated in this exception's detail message.
+	 * 
+	 * @param message
+	 *            the detail message (which is saved for later retrieval by the
+	 *            {@link #getMessage()} method).
+	 * @param cause
+	 *            the cause (which is saved for later retrieval by the
+	 *            {@link #getCause()} method). (A <tt>null</tt> value is
+	 *            permitted, and indicates that the cause is nonexistent or
+	 *            unknown.)
+	 * @since 1.4
+	 */
+	public BizException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public BizException(Throwable cause) {
+		super(cause);
+	}
+}

+ 195 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/job/entity/JobInfo.java

@@ -0,0 +1,195 @@
+package com.xtframe.core.job.entity;
+
+import java.util.Date;
+
+/**
+ * 定时任务对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface JobInfo {
+
+    /**
+     * 是否循环
+     * 
+     * @return
+     */
+    public Boolean getCircle();
+
+    /**
+     * 执行接口
+     * 
+     * @return
+     */
+    public String getClazz();
+
+    /**
+     * 任务创建时间
+     * 
+     * @return
+     */
+    public Date getCreateTime();
+
+    /**
+     * 获取调度表达式
+     * 
+     * @return
+     */
+    public String getCronExpression();
+
+    /**
+     * 任务描述
+     * 
+     * @return
+     */
+    public String getDisp();
+
+    /**
+     * 任务结束时间
+     * 
+     * @return
+     */
+    public Date getEndTime();
+
+    /**
+     * 任务主键
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 间隔时间(秒)
+     * 
+     * @return
+     */
+    public int getInterval();
+
+    /**
+     * 任务分组
+     * 
+     * @return
+     */
+    public String getJobGroup();
+
+    /**
+     * 任务名称
+     * 
+     * @return
+     */
+    public String getJobName();
+
+    /**
+     * 执行参数
+     * 
+     * @return
+     */
+    public String getParam();
+
+    /**
+     * 上次执行结果
+     * 
+     * @return
+     */
+    public String getResult();
+
+    /**
+     * 任务启动时间,正式开始运行任务的时间
+     * 
+     * @return
+     */
+    public Date getStartTime();
+
+    /**
+     * 任务状态
+     * 
+     * @return
+     */
+    public String getStatus();
+
+    /**
+     * 是否循环
+     * 
+     * @param circle
+     */
+    public void setCircle(Boolean circle);
+
+    /**
+     * 执行接口
+     * 
+     * @param clazz
+     */
+    public void setClazz(String clazz);
+
+    /**
+     * 任务创建时间
+     * 
+     * @param createTime
+     */
+    public void setCreateTime(Date createTime);
+
+    /**
+     * 获取调度表达式
+     * 
+     * @param cronExpression
+     */
+    public void setCronExpression(String cronExpression);
+
+    /**
+     * 任务描述
+     * 
+     * @param disp
+     */
+    public void setDisp(String disp);
+
+    /**
+     * 任务结束时间
+     * 
+     * @param endTime
+     */
+    public void setEndTime(Date endTime);
+
+    /**
+     * 任务ID
+     * 
+     * @param id
+     */
+    public void setId(String id);
+
+    /**
+     * 任务执行间隔时间
+     * 
+     * @param interval
+     */
+    public void setInterval(int interval);
+
+    /**
+     * 执行参数
+     * 
+     * @param param
+     */
+    public void setParam(String param);
+
+    /**
+     * 上次执行结果
+     * 
+     * @param result
+     */
+    public void setResult(String result);
+
+    /**
+     * 任务启动时间,正式开始运行任务的时间
+     * 
+     * @param startTime
+     */
+    public void setStartTime(Date startTime);
+
+    /**
+     * 任务状态
+     * 
+     * @param status
+     */
+    public void setStatus(String status);
+
+}

+ 98 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/job/service/JobInfoService.java

@@ -0,0 +1,98 @@
+package com.xtframe.core.job.service;
+
+import java.util.List;
+
+import com.xtframe.core.job.entity.JobInfo;
+
+/**
+ * 定时任务服务接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface JobInfoService {
+    String PARAM_JOB = "jobInfo";
+
+    /***
+     * 添加定时任务
+     * 
+     * @return 成功返回大于0,失败返回小于0
+     */
+    public int addJob(JobInfo jobInfo);
+
+    /**
+     * 暂停指定任务
+     * 
+     * @param jobInfo
+     * @return 成功返回大于0,失败返回小于0
+     */
+    public int pauseJob(JobInfo jobInfo);
+
+    /**
+     * 删除指定任务
+     * 
+     * @param jobInfo
+     * @return 成功返回大于0,失败返回小于0
+     */
+    public int deleteJob(JobInfo jobInfo);
+
+    /**
+     * 恢复任务执行
+     * 
+     * @param jobInfo
+     * @return
+     */
+    public int resumeJob(JobInfo jobInfo);
+
+    /**
+     * service初始化处理
+     */
+    public void initJobs(Object param);
+
+    /**
+     * 查询所有设定的任务
+     * 
+     * @return
+     */
+    public List<JobInfo> queryAllJob();
+
+    /**
+     * 立即运行任务
+     * 
+     * @param jobInfo
+     * @return 成功返回大于0,失败返回小于0
+     */
+    public int triggerJob(JobInfo jobInfo);
+
+    /**
+     * 更新任务
+     * 
+     * @param jobInfo
+     * @return 成功返回大于0,失败返回小于0
+     */
+    public int updateJob(JobInfo jobInfo);
+
+    /**
+     * 根据任务ID查找任务
+     * 
+     * @param id
+     * @return
+     */
+    public JobInfo findOne(String id);
+
+    /**
+     * 保存任务信息
+     * 
+     * @param code
+     * @return
+     */
+    public JobInfo save(JobInfo code);
+
+    /**
+     * 删除任务信息,需要手动停止正在运行的此项任务
+     * 
+     * @param ids
+     * @return
+     */
+    public String delete(String... ids);
+}

+ 50 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/log/BizLogRecorder.java

@@ -0,0 +1,50 @@
+package com.xtframe.core.log;
+
+/**
+ * 业务日志记录
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface BizLogRecorder {
+    /** 定义日志类型 */
+    public enum HandlerType {
+        /** 登录 */
+        PreHandle("pre"),
+        /** 登出 */
+        PostHandle("post"),
+        /** 新增 */
+        AfterCompletion("afterCompletion"),
+        /** 异常 */
+        Exception("exception");
+        private String value;
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        private HandlerType(String value) {
+            this.value = value;
+        }
+    };
+
+    /**
+     * 记录日志
+     * 
+     * @param request
+     *            一般为HttpServletRequest
+     * @param response
+     *            一般为HttpServletResponse,当type类型为异常时可以放入异常对象
+     * @param handler
+     *            一般为HandlerMethod
+     * @param type
+     *            HandlerType
+     * @param cost
+     *            执行花费
+     */
+    public void log(Object request, Object response, Object handler, HandlerType type, long cost);
+}

+ 107 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/entity/Function.java

@@ -0,0 +1,107 @@
+package com.xtframe.core.menu.entity;
+
+/**
+ * 菜单下功能对象接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface Function {
+    /**
+     * 获取编码
+     * 
+     * @return
+     */
+    public String getCode();
+
+    /**
+     * 获取功能图标
+     * 
+     * @return
+     */
+    public String getIcon();
+
+    /**
+     * 获取能唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 获取所属菜单
+     * 
+     * @return
+     */
+    public Menu getMenu();
+
+    /**
+     * 获取功能名称
+     * 
+     * @return
+     */
+    public String getName();
+
+    /**
+     * 设置功能相对于本级的排序号
+     * 
+     * @return
+     */
+    public int getSortno();
+
+    /**
+     * 是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 设置编码
+     * 
+     * @param code
+     */
+    public void setCode(String code);
+
+    /**
+     * 设置功能图标
+     * 
+     * @return
+     */
+    public void setIcon(String icon);
+
+    /**
+     * 设置功能唯一标识
+     * 
+     * @return
+     */
+    public void setId(String id);
+
+    /**
+     * 设置所属菜单
+     * 
+     * @param menu
+     */
+    public void setMenu(Menu menu);
+
+    /**
+     * 设置功能名称
+     * 
+     * @return
+     */
+    public void setName(String name);
+
+    /**
+     * 设置功能相对于本级的排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno);
+
+    /**
+     * 是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+}

+ 158 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/entity/Menu.java

@@ -0,0 +1,158 @@
+package com.xtframe.core.menu.entity;
+
+/**
+ * 菜单对象接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface Menu {
+    /**
+     * 获取菜单编码
+     * 
+     * @return
+     */
+    public String getCode();
+
+    /**
+     * 获取菜单图标
+     * 
+     * @return
+     */
+    public String getIcon();
+
+    /**
+     * 第二种式样
+     * 
+     * @return
+     */
+    public String getIcon2();
+
+    /**
+     * 获取菜单唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 获取是否叶子节点
+     * 
+     * @return
+     */
+    public Boolean getLeaf();
+
+    /**
+     * 获取菜单名称
+     * 
+     * @return
+     */
+    public String getName();
+
+    /**
+     * 是否外部链接<br>
+     * 外部链接需要提供完整url
+     * 
+     * @return
+     */
+    public Boolean getOutLink();
+
+    /**
+     * 获取上级ID
+     * 
+     * @return
+     */
+    public String getPid();
+
+    /**
+     * 设置菜单相对于本级的排序号
+     * 
+     * @return
+     */
+    public int getSortno();
+
+    /**
+     * 获取菜单路径
+     * 
+     * @return
+     */
+    public String getUrl();
+
+    /**
+     * 是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 设置菜单编码
+     * 
+     * @param code
+     */
+    public void setCode(String code);
+
+    /**
+     * 设置菜单图标
+     * 
+     * @return
+     */
+    public void setIcon(String icon);
+
+    /**
+     * 第二种式样
+     * 
+     * @param icon2
+     */
+    public void setIcon2(String icon2);
+
+    /**
+     * 设置菜单唯一标识
+     * 
+     * @return
+     */
+    public void setId(String id);
+
+    /**
+     * 设置是否叶子节点
+     * 
+     * @param leaf
+     */
+    public void setLeaf(Boolean leaf);
+
+    /**
+     * 设置菜单名称
+     * 
+     * @return
+     */
+    public void setName(String name);
+
+    /**
+     * 是否外部链接<br>
+     * 外部链接需要提供完整url
+     * 
+     * @param outLink
+     */
+    public void setOutLink(Boolean outLink);
+
+    /**
+     * 设置菜单相对于本级的排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno);
+
+    /**
+     * 设置菜单路径
+     * 
+     * @param url
+     */
+    public void setUrl(String url);
+
+    /**
+     * 是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+}

+ 246 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/menu/service/MenuService.java

@@ -0,0 +1,246 @@
+package com.xtframe.core.menu.service;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.xtframe.core.base.vo.NodeVo;
+import com.xtframe.core.menu.entity.Function;
+import com.xtframe.core.menu.entity.Menu;
+
+/**
+ * 菜单服务
+ * 
+ * @author 袁晓冬
+ *
+ * @param <T>
+ */
+public interface MenuService {
+    /**
+     * 根据主键删除菜单
+     * 
+     * @param ids
+     *            主键数组
+     * @return
+     */
+    public String delete(String... ids);
+
+    /**
+     * 删除组织功能关联关系
+     * 
+     * @param orgId
+     * @param functionIds
+     */
+    public void deleteOrgFunctionMap(String orgId, String... functionIds);
+
+    /**
+     * 删除组织菜单关联关系
+     * 
+     * @param orgId
+     * @param menuIds
+     */
+    public void deleteOrgMenuMap(String orgId, String... menuIds);
+
+    /**
+     * 删除角色功能关联关系
+     * 
+     * @param roleId
+     * @param functionIds
+     */
+    public void deleteRoleFunctionMap(String roleId, String... functionIds);
+
+    /**
+     * 删除角色菜单关联关系
+     * 
+     * @param roleId
+     * @param menuIds
+     */
+    public void deleteRoleMenuMap(String roleId, String... menuIds);
+
+    /**
+     * 删除用户菜单关联关系
+     * 
+     * @param userId
+     * @param menuIds
+     */
+    public void deleteUserMenuMap(String userId, String... menuIds);
+
+    /**
+     * 获取首页手风琴菜单<br>
+     * 可以是系统列表,也可以是菜单
+     * 
+     * @return
+     */
+    public List<Menu> findAccordionMenus();
+
+    /**
+     * 获取授权的下级有效菜单
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Menu> findAuthedMenuByPid(String pid);
+
+    /**
+     * 根据主键查找功能
+     * 
+     * @param id
+     * @return
+     */
+    public Function findFunction(String id);
+
+    /**
+     * 根据主键ID检索多个功能
+     * 
+     * @param id
+     * @return
+     */
+    public List<Function> findFunctionByIds(String... id);
+
+    /**
+     * 根据主键查找菜单
+     * 
+     * @param id
+     * @return
+     */
+    public Menu findMenu(String id);
+
+    /**
+     * 根据主键ID检索多个菜单
+     * 
+     * @param id
+     * @return
+     */
+    public List<Menu> findMenuByIds(String... id);
+
+    /**
+     * 根据组织ID获取授权功能集合
+     * 
+     * @param orgId
+     * @return
+     */
+    public List<Function> findValidFunctionByOrgId(final String orgId);
+
+    /**
+     * 根据角色ID获取授权功能集合
+     * 
+     * @param roleId
+     * @return
+     */
+    public List<Function> findValidFunctionByRoleId(final String roleId);
+
+    /**
+     * 根据用户ID获取授权的功能
+     * 
+     * @param userId
+     * @return
+     */
+    public List<Function> findValidFunctionByUserId(final String userId);
+
+    /**
+     * 根据组织获取授权的菜单
+     */
+    public List<Menu> findValidMenuByOrgId(final String orgId);
+
+    /**
+     * 根据上级菜单ID获取下级有效菜单
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Menu> findValidMenuByPid(final String pid);
+
+    /**
+     * 根据角色ID获取授权的菜单
+     * 
+     * @param roleId
+     * @return
+     */
+    public List<Menu> findValidMenuByRoleId(final String roleId);
+
+    /**
+     * 根据用户ID获取授权的菜单
+     * 
+     * @param userId
+     * @return
+     */
+    public List<Menu> findValidMenuByUserId(final String userId);
+
+    /**
+     * 根据上级菜单ID和授权菜单列表获取下级菜单节点
+     * 
+     * @param pid
+     * @param authedMenus
+     * @param authedFuncs
+     * @param cascade
+     * @return
+     */
+    public List<NodeVo> getCheckedMenusByPid(String pid, Collection<Menu> authedMenus,
+            Collection<Function> authedFuncs, boolean cascade);
+
+    /**
+     * 保存菜单
+     * 
+     * @param u
+     * @return
+     */
+    public Menu save(Menu u);
+
+    /**
+     * 保存菜单功能
+     * 
+     * @param f
+     * @return
+     */
+    public Function saveFunction(Function f);
+
+    /**
+     * 保存组织功能关联关系
+     * 
+     * @param orgId
+     * @param functionIds
+     */
+    public void saveOrgFunctionMap(String orgId, String... functionIds);
+
+    /**
+     * 保存组织菜单关联关系
+     * 
+     * @param orgId
+     *            组织ID
+     * @param menuIds
+     */
+    public void saveOrgMenuMap(String orgId, String... menuIds);
+
+    /**
+     * 保存角色功能关联关系
+     * 
+     * @param roleId
+     * @param functionIds
+     */
+    public void saveRoleFunctionMap(String roleId, String... functionIds);
+
+    /**
+     * 保存角色菜单关联关系
+     * 
+     * @param roleId
+     * @param menuIds
+     */
+    public void saveRoleMenuMap(String roleId, String... menuIds);
+
+    /**
+     * 保存用户功能映射关系
+     * 
+     * @param userid
+     * @param funcIds
+     */
+    public void saveUserFunctionMap(String userid, String... funcIds);
+
+    /**
+     * 保存用户菜单关联关系
+     * 
+     * @param userId
+     *            用户ID
+     * @param menuIds
+     *            菜单ID数组
+     */
+    public void saveUserMenuMap(String userId, String... menuIds);
+}

+ 105 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/org/entity/Org.java

@@ -0,0 +1,105 @@
+package com.xtframe.core.org.entity;
+
+/**
+ * 组织对象接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface Org {
+    /**
+     * 获取组织编码(00100F...十六进制式方便进行like查询)
+     * 
+     * @return
+     */
+    public String getCode();
+
+    /**
+     * 获取组织唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 获取组织名称
+     * 
+     * @return
+     */
+    public String getName();
+
+    /**
+     * 获取上级ID
+     * 
+     * @return
+     */
+    public String getPid();
+
+    /**
+     * 备注
+     * 
+     * @return
+     */
+    public String getRemark();
+
+    /**
+     * 排序号
+     * 
+     * @return
+     */
+    public int getSortno();
+
+    /**
+     * 是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 设置组织编码(00100F...十六进制式方便进行like查询)
+     */
+    public void setCode(String code);
+
+    /**
+     * 设置组织唯一标识
+     * 
+     * @return
+     */
+    public void setId(String id);
+
+    /**
+     * 设置组织名称
+     * 
+     * @return
+     */
+    public void setName(String name);
+
+    /**
+     * 设置上级组织ID
+     * 
+     * @param id
+     */
+    public void setPid(String id);
+
+    /**
+     * 备注
+     * 
+     * @param remark
+     */
+    public void setRemark(String remark);
+
+    /**
+     * 排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno);
+
+    /**
+     * 是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+}

+ 80 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/org/service/OrgService.java

@@ -0,0 +1,80 @@
+package com.xtframe.core.org.service;
+
+import java.util.List;
+
+import com.xtframe.core.org.entity.Org;
+
+/**
+ * 组织服务
+ * 
+ * @author 袁晓冬
+ *
+ * @param <T>
+ */
+public interface OrgService {
+
+	/**
+	 * 根据主键删除记录
+	 * 
+	 * @param ids
+	 * @return
+	 */
+	public String delete(String... ids);
+
+	/**
+	 * 根据组织code进行检索
+	 * 
+	 * @param code
+	 * @return
+	 */
+	public List<Org> findByCode(String code);
+
+	/**
+	 * 根据组织code进行like检索
+	 * 
+	 * @param code
+	 * @return
+	 */
+	public List<Org> findByCodeLike(String code);
+
+	/**
+	 * 根据上级组织ID检索分页下级
+	 * 
+	 * @param pid
+	 * @param pageable
+	 * @return
+	 */
+	public Object findByPid(String pid, Object pageable);
+
+	/**
+	 * 根据主键查找实体
+	 * 
+	 * @param id
+	 * @return
+	 */
+	public Org findOne(String id);
+
+	/**
+	 * 根据上级ID查找下级有效记录
+	 * 
+	 * @param pid
+	 * @return
+	 */
+	public List<Org> findValidOrgsByPid(String pid);
+
+	/**
+	 * 保存实体
+	 * 
+	 * @param u
+	 * @return
+	 */
+	public Org save(Org u);
+
+	/**
+	 * 根据下级code检索上级
+	 * 
+	 * @param orgCode
+	 * @return
+	 */
+	public List<Org> findBySubCode(String orgCode);
+}

+ 94 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/role/entity/Role.java

@@ -0,0 +1,94 @@
+package com.xtframe.core.role.entity;
+
+
+/**
+ * 角色对象接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface Role {
+    /**
+     * 角色编码
+     * 
+     * @return
+     */
+    public String getCode();
+
+    /**
+     * 用户唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 角色名称
+     * 
+     * @return
+     */
+    public String getName();
+
+    /**
+     * 获取所在组织ID
+     * 
+     * @return
+     */
+    public String getOrgid();
+
+    /**
+     * 排序号
+     * 
+     * @return
+     */
+    public int getSortno();
+
+    /**
+     * 用户是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 设置角色编码
+     * 
+     * @param code
+     */
+    public void setCode(String code);
+
+    /**
+     * 设置唯一标识
+     * 
+     * @param id
+     */
+    public void setId(String id);
+
+    /**
+     * 设置用户名称
+     * 
+     * @param name
+     */
+    public void setName(String name);
+
+    /**
+     * 设置所在组织ID
+     * 
+     * @param orgid
+     */
+    public void setOrgid(String orgid);
+
+    /**
+     * 排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno);
+
+    /**
+     * 设置是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+}

+ 106 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/role/service/RoleService.java

@@ -0,0 +1,106 @@
+package com.xtframe.core.role.service;
+
+import java.util.Collection;
+import java.util.List;
+
+import com.xtframe.core.role.entity.Role;
+
+/**
+ * 角色服务
+ * 
+ * @author 袁晓冬
+ *
+ * @param <T>
+ */
+public interface RoleService {
+    /**
+     * 根据主键删除记录
+     * 
+     * @param ids
+     * @return
+     */
+    public void delete(String... ids);
+
+    /**
+     * 查找所有有效角色
+     * 
+     * @return
+     */
+    public List<Role> findAll();
+
+    /**
+     * 根据用户名查询用户
+     * 
+     * @param uname
+     * @return
+     */
+    public List<Role> findByCode(String code);
+
+    /**
+     * 根据角色编码和所在组织编码检索角色
+     * 
+     * @param code
+     * @param orgCodes
+     * @return
+     */
+    public List<Role> findByCodeAndOrgCodeIn(String code, Collection<String> orgCodes);
+
+    /**
+     * 根据角色编码和所在组织ID检索角色
+     * 
+     * @param code
+     * @param orgId
+     * @return
+     */
+    public List<Role> findByCodeAndOrgIdIn(String code, Collection<String> orgCodes);
+
+    /**
+     * 根据角色编码查找指定组织的上级组织(不包含本级组织)
+     * 
+     * @param code
+     * @param org
+     * @return
+     */
+    public List<Role> findByCodeAndPOrgCode(String code, String orgCode);
+
+    public List<Role> findByCodeAndSubOrgCode(String code, String orgCode);
+
+    /**
+     * 根据用户唯一标识查询
+     * 
+     * @param id
+     * @return
+     */
+    public Role findById(String id);
+
+    /**
+     * 根据组织编码获取角色
+     * 
+     * @param orgCode
+     * @return
+     */
+    public List<Role> findByOrgCode(String orgCode);
+
+    /**
+     * 根据组织ID获取角色
+     * 
+     * @param org
+     * @return
+     */
+    public List<Role> findByOrgid(String org);
+
+    /**
+     * 根据用户ID查询角色
+     * 
+     * @return
+     */
+    public List<Role> findByUserId(String userid);
+
+    /**
+     * 保存用户
+     * 
+     * @param u
+     * @return
+     */
+    public Role save(Role u);
+}

+ 124 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/SecurityMgr.java

@@ -0,0 +1,124 @@
+package com.xtframe.core.support;
+
+import java.util.List;
+
+import com.xtframe.core.code.service.CodeService;
+import com.xtframe.core.data.service.DataPermService;
+import com.xtframe.core.job.service.JobInfoService;
+import com.xtframe.core.menu.entity.Menu;
+import com.xtframe.core.menu.service.MenuService;
+import com.xtframe.core.org.entity.Org;
+import com.xtframe.core.org.service.OrgService;
+import com.xtframe.core.role.service.RoleService;
+import com.xtframe.core.user.entity.User;
+import com.xtframe.core.user.service.UserService;
+
+/**
+ * 安全相关功能接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface SecurityMgr {
+    /**
+     * 获取字典服务接口
+     * 
+     * @return
+     */
+    CodeService codeService();
+
+    /**
+     * 数据权限操作接口
+     * 
+     * @return
+     */
+    DataPermService dataPermService();
+
+    /**
+     * 获取下级授权的有效菜单,pid为空时返回第一层菜单
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Menu> findPermittedMenusByPid(String pid);
+
+    /**
+     * 获取下级有效菜单,不进行授权过滤
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Menu> findValidMenusByPid(String pid);
+
+    /**
+     * 获取当前登录用户
+     * 
+     * @return
+     */
+    public User getCurrUser();
+
+    /**
+     * 获取当前登录用户所在组织
+     * 
+     * @return
+     */
+    public Org getCurrUserOrg();
+
+    /**
+     * 获取session属性
+     * 
+     * @param attr
+     * @return
+     */
+    public Object getSessionAttr(Object attr);
+
+    /**
+     * 判断用户是否已经过身份验证
+     * 
+     * @return
+     */
+    boolean isAuthenticated();
+
+    /**
+     * 定时任务服务接口
+     * 
+     * @return
+     */
+    JobInfoService jobService();
+
+    /**
+     * 获取菜单服务接口
+     * 
+     * @return
+     */
+    MenuService menuService();
+
+    /**
+     * 组织服务
+     * 
+     * @return
+     */
+    OrgService orgService();
+
+    /**
+     * 获取角色服务接口
+     * 
+     * @return
+     */
+    RoleService roleService();
+
+    /**
+     * 设置session属性
+     * 
+     * @param name
+     * @param value
+     */
+    public void setSessionAttr(Object name, Object value);
+
+    /**
+     * 用户服务接口
+     * 
+     * @return
+     */
+    UserService userService();
+}

+ 8 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/SessionMgr.java

@@ -0,0 +1,8 @@
+package com.xtframe.core.support;
+
+/**
+ * Session管理接口
+ */
+public interface SessionMgr {
+	Object getAttribute(Object key);
+}

+ 14 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/WorkFlowMgr.java

@@ -0,0 +1,14 @@
+package com.xtframe.core.support;
+
+import com.xtframe.core.wf.WorkFlowEngineClient;
+
+/**
+ * 工作流相关功能接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface WorkFlowMgr {
+    /** 获取流程执行客户端接口 */
+    WorkFlowEngineClient workFlowEngineClient();
+}

+ 14 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/aware/SecurityMgrAware.java

@@ -0,0 +1,14 @@
+package com.xtframe.core.support.aware;
+
+import com.xtframe.core.support.SecurityMgr;
+
+
+/**
+ * 安全服务提供标识
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface SecurityMgrAware {
+    public void setSecurityMgr(SecurityMgr securityMgr);
+}

+ 11 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/support/aware/WorkflowMgrAware.java

@@ -0,0 +1,11 @@
+package com.xtframe.core.support.aware;
+
+/**
+ * 工作流服务提供标识
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface WorkflowMgrAware {
+    public void setWorkflowMgrAware(WorkflowMgrAware orkflowMgrAware);
+}

+ 153 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/user/entity/User.java

@@ -0,0 +1,153 @@
+/** 
+ * 文 件 名 : User.java 
+ * 创 建 人:袁晓冬
+ * 日     期: 2015年6月23日下午5:28:37
+ * 修 改 人: 
+ * 日     期: 
+ * 版 本 号: 
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司
+ */
+package com.xtframe.core.user.entity;
+
+/**
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司
+ * 项 目 名: xtCore-oa
+ * 注 释: 用户对象接口 <br/>
+ * 命名空间: com.xtframe.core.user.entity
+ * 创 建 人: 袁晓冬
+ * 日 期: 2015年6月23日下午5:28:37
+ * 修 改 人:袁晓冬
+ * 日 期:2015年7月6日11:18:09
+ * 修改原因:增加微信号字段
+ * 版 本 号:
+ * 
+ * @since JDK 1.6
+ */
+public interface User {
+
+    /**
+     * 用户唯一标识
+     * 
+     * @return
+     */
+    public String getId();
+
+    /**
+     * 用户名称
+     * 
+     * @return
+     */
+    public String getName();
+
+    /**
+     * 获取用户所在组织ID
+     * 
+     * @return
+     */
+    public String getOrg();
+
+    /**
+     * 获取组织名称
+     * 
+     * @return
+     */
+    public String getOrgName();
+
+    /**
+     * 用户密码
+     * 
+     * @return
+     */
+    public String getPassword();
+
+    /**
+     * 排序号
+     * 
+     * @return
+     */
+    public int getSortno();
+
+    /**
+     * 用户登录账号
+     * 
+     * @return
+     */
+    public String getUname();
+
+    /**
+     * 用户是否有效
+     * 
+     * @return
+     */
+    public Boolean getValid();
+
+    /**
+     * 微信ID
+     * 
+     * @return
+     */
+    public String getWeixinid();
+
+    /**
+     * 设置唯一标识
+     * 
+     * @param id
+     */
+    public void setId(String id);
+
+    /**
+     * 设置用户名称
+     * 
+     * @param name
+     */
+    public void setName(String name);
+
+    /**
+     * 更新用户所在组织
+     * 
+     * @param org
+     */
+    public void setOrg(String org);
+
+    /**
+     * 设置组织名称
+     * 
+     * @param orgName
+     */
+    public void setOrgName(String orgName);
+
+    /**
+     * 设置登录密码
+     * 
+     * @param password
+     */
+    public void setPassword(String password);
+
+    /**
+     * 排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno);
+
+    /**
+     * 设置登录账号
+     * 
+     * @param uname
+     */
+    public void setUname(String uname);
+
+    /**
+     * 设置是否有效
+     * 
+     * @param valid
+     */
+    public void setValid(Boolean valid);
+
+    /**
+     * 微信ID
+     * 
+     * @param weixinid
+     */
+    public void setWeixinid(String weixinid);
+}

+ 97 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/user/service/UserService.java

@@ -0,0 +1,97 @@
+package com.xtframe.core.user.service;
+
+import java.util.List;
+
+import com.xtframe.core.user.entity.User;
+
+/**
+ * 用户服务接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface UserService {
+    /**
+     * 根据主键删除记录
+     * 
+     * @param ids
+     *            用户ID
+     * @return
+     */
+    public String delete(String... ids);
+
+    /**
+     * 删除用户关联的角色
+     * 
+     * @param uid
+     *            用户ID
+     * @param rids
+     *            待删除的用户角色数组
+     */
+    public void deleteUserRoles(String uid, String[] rids);
+
+    /**
+     * 根据用户唯一标识查询
+     * 
+     * @param id
+     *            用户唯一标识
+     * @return User
+     */
+    public User findById(String id);
+
+    /**
+     * 根据组织ID查找用户
+     * 
+     * @param orgId
+     *            用户所在组织ID
+     * @return
+     */
+    public List<User> findByOrg(String orgId);
+
+    /**
+     * 根据组织ID和角色编码过滤本组织下的用户
+     * 
+     * @param orgId
+     *            组织UUID
+     * @param roleCodes
+     *            角色编码code
+     * @return
+     */
+    public List<User> findByOrgAndRoleCode(String orgId, List<String> roleCodes);
+
+    /**
+     * 根据角色查询用户
+     * 
+     * @param roleId
+     * @return
+     */
+    public List<User> findByRole(String roleId);
+
+    /**
+     * 根据用户名查询用户
+     * 
+     * @param uname
+     *            用户登录名称
+     * @return User
+     */
+    public User findByUname(String uname);
+
+    /**
+     * 保存用户
+     * 
+     * @param u
+     *            User用户对象
+     * @return User 用户对象
+     */
+    public User save(User u);
+
+    /**
+     * 保存用户角色关联关系
+     * 
+     * @param uid
+     *            用户ID
+     * @param rids
+     *            角色ID数组
+     */
+    public void saveUserRoles(String uid, String[] rids);
+}

+ 548 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/Assert.java

@@ -0,0 +1,548 @@
+package com.xtframe.core.utils;
+
+import java.util.Collection;
+import java.util.Map;
+
+import com.xtframe.core.exception.BizException;
+import com.xtframe.util.CollectionUtils;
+import com.xtframe.util.ObjectUtils;
+import com.xtframe.util.StringUtils;
+
+/**
+ * 断言共通类
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class Assert {
+
+	/**
+	 * Assert a boolean expression, throwing {@code BizException} if
+	 * the test result is {@code false}.
+	 * 
+	 * <pre class="code">
+	 * Assert.isTrue(i &gt; 0, &quot;The value must be greater than zero&quot;);
+	 * </pre>
+	 * 
+	 * @param expression
+	 *            a boolean expression
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if expression is {@code false}
+	 */
+	public static void isTrue(boolean expression, String message) {
+		if (!expression) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert a boolean expression, throwing {@code BizException} if
+	 * the test result is {@code false}.
+	 * 
+	 * <pre class="code">
+	 * Assert.isTrue(i &gt; 0);
+	 * </pre>
+	 * 
+	 * @param expression
+	 *            a boolean expression
+	 * @throws BizException
+	 *             if expression is {@code false}
+	 */
+	public static void isTrue(boolean expression) {
+		isTrue(expression, "[Assertion failed] - this expression must be true");
+	}
+
+	/**
+	 * Assert that an object is {@code null} .
+	 * 
+	 * <pre class="code">
+	 * Assert.isNull(value, &quot;The value must be null&quot;);
+	 * </pre>
+	 * 
+	 * @param object
+	 *            the object to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the object is not {@code null}
+	 */
+	public static void isNull(Object object, String message) {
+		if (object != null) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that an object is {@code null} .
+	 * 
+	 * <pre class="code">
+	 * Assert.isNull(value);
+	 * </pre>
+	 * 
+	 * @param object
+	 *            the object to check
+	 * @throws BizException
+	 *             if the object is not {@code null}
+	 */
+	public static void isNull(Object object) {
+		isNull(object, "[Assertion failed] - the object argument must be null");
+	}
+
+	/**
+	 * Assert that an object is not {@code null} .
+	 * 
+	 * <pre class="code">
+	 * Assert.notNull(clazz, &quot;The class must not be null&quot;);
+	 * </pre>
+	 * 
+	 * @param object
+	 *            the object to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the object is {@code null}
+	 */
+	public static void notNull(Object object, String message) {
+		if (object == null) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that an object is not {@code null} .
+	 * 
+	 * <pre class="code">
+	 * Assert.notNull(clazz);
+	 * </pre>
+	 * 
+	 * @param object
+	 *            the object to check
+	 * @throws BizException
+	 *             if the object is {@code null}
+	 */
+	public static void notNull(Object object) {
+		notNull(object, "[Assertion failed] - this argument is required; it must not be null");
+	}
+
+	/**
+	 * Assert that the given String is not empty; that is, it must not be
+	 * {@code null} and not the empty String.
+	 * 
+	 * <pre class="code">
+	 * Assert.hasLength(name, &quot;Name must not be empty&quot;);
+	 * </pre>
+	 * 
+	 * @param text
+	 *            the String to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @see StringUtils#hasLength
+	 */
+	public static void hasLength(String text, String message) {
+		if (!StringUtils.hasLength(text)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that the given String is not empty; that is, it must not be
+	 * {@code null} and not the empty String.
+	 * 
+	 * <pre class="code">
+	 * Assert.hasLength(name);
+	 * </pre>
+	 * 
+	 * @param text
+	 *            the String to check
+	 * @see StringUtils#hasLength
+	 */
+	public static void hasLength(String text) {
+		hasLength(text, "[Assertion failed] - this String argument must have length; it must not be null or empty");
+	}
+
+	/**
+	 * Assert that the given String has valid text content; that is, it must not
+	 * be {@code null} and must contain at least one non-whitespace character.
+	 * 
+	 * <pre class="code">
+	 * Assert.hasText(name, &quot;'name' must not be empty&quot;);
+	 * </pre>
+	 * 
+	 * @param text
+	 *            the String to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @see StringUtils#hasText
+	 */
+	public static void hasText(String text, String message) {
+		if (!StringUtils.hasText(text)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that the given String has valid text content; that is, it must not
+	 * be {@code null} and must contain at least one non-whitespace character.
+	 * 
+	 * <pre class="code">
+	 * Assert.hasText(name, &quot;'name' must not be empty&quot;);
+	 * </pre>
+	 * 
+	 * @param text
+	 *            the String to check
+	 * @see StringUtils#hasText
+	 */
+	public static void hasText(String text) {
+		hasText(text,
+		        "[Assertion failed] - this String argument must have text; it must not be null, empty,'null', or blank");
+	}
+
+	/**
+	 * 非空字符串判断<br>
+	 * “null”视为空字符串
+	 * 
+	 * @param text
+	 * @param message
+	 */
+	public static void notBlank(String text, String message) {
+		if (!StringUtils.hasText(text) || "null".equalsIgnoreCase(message)) {
+			throw new BizException(message);
+		}
+	}
+
+	public static void notBlank(String text) {
+		notBlank(text,
+		        "[Assertion failed] - this String argument must have text; it must not be null, empty,'null', or blank");
+	}
+
+	/**
+	 * Assert that the given text does not contain the given substring.
+	 * 
+	 * <pre class="code">
+	 * Assert.doesNotContain(name, &quot;rod&quot;, &quot;Name must not contain 'rod'&quot;);
+	 * </pre>
+	 * 
+	 * @param textToSearch
+	 *            the text to search
+	 * @param substring
+	 *            the substring to find within the text
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 */
+	public static void doesNotContain(String textToSearch, String substring, String message) {
+		if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that the given text does not contain the given substring.
+	 * 
+	 * <pre class="code">
+	 * Assert.doesNotContain(name, &quot;rod&quot;);
+	 * </pre>
+	 * 
+	 * @param textToSearch
+	 *            the text to search
+	 * @param substring
+	 *            the substring to find within the text
+	 */
+	public static void doesNotContain(String textToSearch, String substring) {
+		doesNotContain(textToSearch, substring,
+		        "[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
+	}
+
+	/**
+	 * Assert that an array has elements; that is, it must not be {@code null}
+	 * and must have at least one element.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(array, &quot;The array must have elements&quot;);
+	 * </pre>
+	 * 
+	 * @param array
+	 *            the array to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the object array is {@code null} or has no elements
+	 */
+	public static void notEmpty(Object[] array, String message) {
+		if (ObjectUtils.isEmpty(array)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that an array has elements; that is, it must not be {@code null}
+	 * and must have at least one element.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(array);
+	 * </pre>
+	 * 
+	 * @param array
+	 *            the array to check
+	 * @throws BizException
+	 *             if the object array is {@code null} or has no elements
+	 */
+	public static void notEmpty(Object[] array) {
+		notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
+	}
+
+	/**
+	 * Assert that an array has no null elements. Note: Does not complain if the
+	 * array is empty!
+	 * 
+	 * <pre class="code">
+	 * Assert.noNullElements(array, &quot;The array must have non-null elements&quot;);
+	 * </pre>
+	 * 
+	 * @param array
+	 *            the array to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the object array contains a {@code null} element
+	 */
+	public static void noNullElements(Object[] array, String message) {
+		if (array != null) {
+			for (Object element : array) {
+				if (element == null) {
+					throw new BizException(message);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Assert that an array has no null elements. Note: Does not complain if the
+	 * array is empty!
+	 * 
+	 * <pre class="code">
+	 * Assert.noNullElements(array);
+	 * </pre>
+	 * 
+	 * @param array
+	 *            the array to check
+	 * @throws BizException
+	 *             if the object array contains a {@code null} element
+	 */
+	public static void noNullElements(Object[] array) {
+		noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
+	}
+
+	/**
+	 * Assert that a collection has elements; that is, it must not be
+	 * {@code null} and must have at least one element.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(collection, &quot;Collection must have elements&quot;);
+	 * </pre>
+	 * 
+	 * @param collection
+	 *            the collection to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the collection is {@code null} or has no elements
+	 */
+	public static void notEmpty(Collection<?> collection, String message) {
+		if (CollectionUtils.isEmpty(collection)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that a collection has elements; that is, it must not be
+	 * {@code null} and must have at least one element.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(collection, &quot;Collection must have elements&quot;);
+	 * </pre>
+	 * 
+	 * @param collection
+	 *            the collection to check
+	 * @throws BizException
+	 *             if the collection is {@code null} or has no elements
+	 */
+	public static void notEmpty(Collection<?> collection) {
+		notEmpty(collection,
+		        "[Assertion failed] - this collection must not be empty: it must contain at least 1 element");
+	}
+
+	/**
+	 * Assert that a Map has entries; that is, it must not be {@code null} and
+	 * must have at least one entry.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(map, &quot;Map must have entries&quot;);
+	 * </pre>
+	 * 
+	 * @param map
+	 *            the map to check
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if the map is {@code null} or has no entries
+	 */
+	public static void notEmpty(Map<?, ?> map, String message) {
+		if (CollectionUtils.isEmpty(map)) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert that a Map has entries; that is, it must not be {@code null} and
+	 * must have at least one entry.
+	 * 
+	 * <pre class="code">
+	 * Assert.notEmpty(map);
+	 * </pre>
+	 * 
+	 * @param map
+	 *            the map to check
+	 * @throws BizException
+	 *             if the map is {@code null} or has no entries
+	 */
+	public static void notEmpty(Map<?, ?> map) {
+		notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
+	}
+
+	/**
+	 * Assert that the provided object is an instance of the provided class.
+	 * 
+	 * <pre class="code">
+	 * Assert.instanceOf(Foo.class, foo);
+	 * </pre>
+	 * 
+	 * @param clazz
+	 *            the required class
+	 * @param obj
+	 *            the object to check
+	 * @throws BizException
+	 *             if the object is not an instance of clazz
+	 * @see Class#isInstance
+	 */
+	public static void isInstanceOf(Class<?> clazz, Object obj) {
+		isInstanceOf(clazz, obj, "");
+	}
+
+	/**
+	 * Assert that the provided object is an instance of the provided class.
+	 * 
+	 * <pre class="code">
+	 * Assert.instanceOf(Foo.class, foo);
+	 * </pre>
+	 * 
+	 * @param type
+	 *            the type to check against
+	 * @param obj
+	 *            the object to check
+	 * @param message
+	 *            a message which will be prepended to the message produced by
+	 *            the function itself, and which may be used to provide context.
+	 *            It should normally end in a ": " or ". " so that the function
+	 *            generate message looks ok when prepended to it.
+	 * @throws BizException
+	 *             if the object is not an instance of clazz
+	 * @see Class#isInstance
+	 */
+	public static void isInstanceOf(Class<?> type, Object obj, String message) {
+		notNull(type, "Type to check against must not be null");
+		if (!type.isInstance(obj)) {
+			throw new BizException((StringUtils.hasLength(message) ? message + " " : "")
+			        + "Object of class [" + (obj != null ? obj.getClass().getName() : "null")
+			        + "] must be an instance of " + type);
+		}
+	}
+
+	/**
+	 * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}.
+	 * 
+	 * <pre class="code">
+	 * Assert.isAssignable(Number.class, myClass);
+	 * </pre>
+	 * 
+	 * @param superType
+	 *            the super type to check
+	 * @param subType
+	 *            the sub type to check
+	 * @throws BizException
+	 *             if the classes are not assignable
+	 */
+	public static void isAssignable(Class<?> superType, Class<?> subType) {
+		isAssignable(superType, subType, "");
+	}
+
+	/**
+	 * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}.
+	 * 
+	 * <pre class="code">
+	 * Assert.isAssignable(Number.class, myClass);
+	 * </pre>
+	 * 
+	 * @param superType
+	 *            the super type to check against
+	 * @param subType
+	 *            the sub type to check
+	 * @param message
+	 *            a message which will be prepended to the message produced by
+	 *            the function itself, and which may be used to provide context.
+	 *            It should normally end in a ": " or ". " so that the function
+	 *            generate message looks ok when prepended to it.
+	 * @throws BizException
+	 *             if the classes are not assignable
+	 */
+	public static void isAssignable(Class<?> superType, Class<?> subType, String message) {
+		notNull(superType, "Type to check against must not be null");
+		if (subType == null || !superType.isAssignableFrom(subType)) {
+			throw new BizException(message + subType + " is not assignable to " + superType);
+		}
+	}
+
+	/**
+	 * Assert a boolean expression, throwing {@code BizException} if
+	 * the test result is {@code false}. Call isTrue if you wish to throw
+	 * BizException on an assertion failure.
+	 * 
+	 * <pre class="code">
+	 * Assert.state(id == null, &quot;The id property must not already be initialized&quot;);
+	 * </pre>
+	 * 
+	 * @param expression
+	 *            a boolean expression
+	 * @param message
+	 *            the exception message to use if the assertion fails
+	 * @throws BizException
+	 *             if expression is {@code false}
+	 */
+	public static void state(boolean expression, String message) {
+		if (!expression) {
+			throw new BizException(message);
+		}
+	}
+
+	/**
+	 * Assert a boolean expression, throwing {@link BizException} if
+	 * the test result is {@code false}.
+	 * <p>
+	 * Call {@link #isTrue(boolean)} if you wish to throw
+	 * {@link BizException} on an assertion failure.
+	 * 
+	 * <pre class="code">
+	 * Assert.state(id == null);
+	 * </pre>
+	 * 
+	 * @param expression
+	 *            a boolean expression
+	 * @throws BizException
+	 *             if the supplied expression is {@code false}
+	 */
+	public static void state(boolean expression) {
+		state(expression, "[Assertion failed] - this state invariant must be true");
+	}
+
+}

+ 24 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/CoreConstants.java

@@ -0,0 +1,24 @@
+package com.xtframe.core.utils;
+
+/**
+ * 框架核心包常量
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface CoreConstants {
+
+	/** 系统公共代码-通用是否 */
+	String CODE_TY_SF = "TY_SF";
+	/** 系统公共代码-通用是否-是 */
+	String CODE_TY_SF_YES = "Y";
+	/** 系统公共代码-通用是否-否 */
+	String CODE_TY_SF_NO = "N";
+
+	/** session中存储授权信息的key值 */
+	String SESSION_KEY_AUTH = "_AUTH";
+	/** session中存储组织的key值 */
+	String SESSION_KEY_ORG = "_ORG";
+	/** SESSION中存储系统名称 */
+	String SESSION_SYS_NAME = "_SYS_NAME";
+}

+ 58 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/SystemParam.java

@@ -0,0 +1,58 @@
+package com.xtframe.core.utils;
+
+import java.util.Map;
+
+/**
+ * 系统参数对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class SystemParam {
+    /**
+     * 根据参数名称获取参数值
+     * 
+     * @param name
+     * @return
+     */
+    public static String get(String name) {
+        if (null == paramMap) { return null; }
+        return paramMap.get(name);
+    }
+
+    /**
+     * 获取系统名称
+     * 
+     * @return
+     */
+    public static String getAppName() {
+        return appName;
+    }
+
+    /**
+     * 获取系统初始化默认密码
+     * 
+     * @return
+     */
+    public static String getDefaultPwd() {
+        return defaultPwd;
+    }
+
+    /**
+     * 是否记录业务日志
+     * 
+     * @return
+     */
+    public static boolean isSaveBizLog() {
+        return "true".equalsIgnoreCase(saveBizLog);
+    }
+
+    private static Map<String, String> paramMap = null;
+
+    private static String appName;
+
+    private static String defaultPwd;
+
+    private static String saveBizLog = "false";
+
+}

+ 50 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/utils/WorkflowConsts.java

@@ -0,0 +1,50 @@
+package com.xtframe.core.utils;
+
+/**
+ * 流程常量
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface WorkflowConsts {
+    /** 流程属性-流程启动类型 */
+    String WF_START_TYPE = "s_startType";
+    /** 流程属性-角色ID */
+    String WF_ROLE_ID = "s_roleId";
+    /** 流程属性-发送人角色ID */
+    String WF_SENDER_ROLE_ID = "s_sender_roleId";
+    /** 流程属性-发送人ID */
+    String WF_SENDER_ID = "s_sender_id";
+    /** 流程属性-发送人名称 */
+    String WF_SENDER_NAME = "s_sender_name";
+    /** 流程属性-发送人所在组织ID */
+    String WF_SENDER_ORG_ID = "s_sender_org_id";
+    /** 流程属性-发送人所在组织名称 */
+    String WF_SENDER_ORG_NAME = "s_sender_org_name";
+    /** 发送时间 */
+    String WF_SEND_TIME = "s_send_time";
+    /** 任务处理页面URL */
+    String WF_TASK_URL = "s_task_url";
+    /** 业务名称 */
+    String WF_BIZ_NAME = "s_biz_name";
+    /** 处理结果 */
+    String WF_HANDLER_RESULT = "s_handle_result";
+    /** 处理意见 */
+    String WF_HANDLER_REMARK = "s_handle_remark";
+    /** 下一步处理人 */
+    String WF_BIZ_HANDLERS = "handlers";
+    /** 下一步跳转步骤 */
+    String WF_BIZ_NEXT_STEP = "next_step";
+    /** 组织操作与角色分隔符 */
+    String WF_GROUP_SEP = "__";
+    /** 组织方向变量:同级、上级、下级 */
+    String WF_GROUP_ORG_DIR = "s_task_org_dir";
+    /** 组织方向:同级 */
+    String WF_GROUP_ORG_DIR_EQ = "eq";
+    /** 组织方向:上级 */
+    String WF_GROUP_ORG_DIR_UP = "gt";
+    /** 组织方向:下级 */
+    String WF_GROUP_ORG_DIR_DW = "dw";
+    /** UEL表达式中当前用户所在组织ID变量 */
+    String WF_UEL_PARAM_CURR_ORG = "currUserOrg";
+}

+ 170 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/Execution.java

@@ -0,0 +1,170 @@
+package com.xtframe.core.wf;
+
+/**
+ * Represent a 'path of execution' in a process instance.
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class Execution {
+
+    /** The unique identifier of the execution. */
+    String id;
+
+    /** Indicates if the execution is suspended. */
+    boolean suspended;
+
+    /** Indicates if the execution is ended. */
+    boolean ended;
+
+    /**
+     * Returns the id of the activity where the execution currently is at.
+     * Returns null if the execution is not a 'leaf' execution (eg concurrent parent).
+     */
+    String activityId;
+    /**
+     * 流程步骤名称
+     */
+    String activityName;
+
+    /**
+     * Id of the root of the execution tree representing the process instance.
+     * It is the same as {@link #getId()} if this execution is the process instance.
+     */
+    String processInstanceId;
+
+    /**
+     * Gets the id of the parent of this execution. If null, the execution represents a process-instance.
+     */
+    String parentId;
+
+    /**
+     * Returns the id of the activity where the execution currently is at.
+     * Returns null if the execution is not a 'leaf' execution (eg concurrent parent).
+     * 
+     * @return
+     */
+    public String getActivityId() {
+        return activityId;
+    }
+
+    /**
+     * 流程步骤名称
+     * 
+     * @return
+     */
+    public String getActivityName() {
+        return activityName;
+    }
+
+    /**
+     * The unique identifier of the execution.
+     * 
+     * @return
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * Gets the id of the parent of this execution. If null, the execution represents a process-instance.
+     * 
+     * @return
+     */
+    public String getParentId() {
+        return parentId;
+    }
+
+    /**
+     * Id of the root of the execution tree representing the process instance.
+     * It is the same as {@link #getId()} if this execution is the process instance.
+     * 
+     * @return
+     */
+    public String getProcessInstanceId() {
+        return processInstanceId;
+    }
+
+    /**
+     * Indicates if the execution is ended.
+     * 
+     * @return
+     */
+    public boolean isEnded() {
+        return ended;
+    }
+
+    /**
+     * Indicates if the execution is suspended.
+     * 
+     * @return
+     */
+    public boolean isSuspended() {
+        return suspended;
+    }
+
+    /**
+     * Returns the id of the activity where the execution currently is at.
+     * Returns null if the execution is not a 'leaf' execution (eg concurrent parent).
+     * 
+     * @param activityId
+     */
+    public void setActivityId(String activityId) {
+        this.activityId = activityId;
+    }
+
+    /**
+     * 流程步骤名称
+     * 
+     * @param activityName
+     */
+    public void setActivityName(String activityName) {
+        this.activityName = activityName;
+    }
+
+    /**
+     * Indicates if the execution is ended.
+     * 
+     * @param ended
+     */
+    public void setEnded(boolean ended) {
+        this.ended = ended;
+    }
+
+    /**
+     * The unique identifier of the execution.
+     * 
+     * @param id
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * Gets the id of the parent of this execution. If null, the execution represents a process-instance.
+     * 
+     * @param parentId
+     */
+    public void setParentId(String parentId) {
+        this.parentId = parentId;
+    }
+
+    /**
+     * Id of the root of the execution tree representing the process instance.
+     * It is the same as {@link #getId()} if this execution is the process instance.
+     * 
+     * @param processInstanceId
+     */
+    public void setProcessInstanceId(String processInstanceId) {
+        this.processInstanceId = processInstanceId;
+    }
+
+    /**
+     * Indicates if the execution is suspended.
+     * 
+     * @param suspended
+     */
+    public void setSuspended(boolean suspended) {
+        this.suspended = suspended;
+    }
+}

+ 72 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/NextTask.java

@@ -0,0 +1,72 @@
+package com.xtframe.core.wf;
+
+import java.util.List;
+
+/**
+ * 下一步信息
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class NextTask {
+	/** 任务名称 */
+	String taskId;
+	/** 任务处理人 */
+	String assignee;
+	/** 任务处理组 */
+	List<String> groups;
+
+	/**
+	 * 任务处理人
+	 * 
+	 * @return
+	 */
+	public String getAssignee() {
+		return assignee;
+	}
+
+	/**
+	 * 任务处理组
+	 * 
+	 * @return
+	 */
+	public List<String> getGroups() {
+		return groups;
+	}
+
+	/**
+	 * 任务名称
+	 * 
+	 * @return
+	 */
+	public String getTaskId() {
+		return taskId;
+	}
+
+	/**
+	 * 任务处理人
+	 * 
+	 * @param assignee
+	 */
+	public void setAssignee(String assignee) {
+		this.assignee = assignee;
+	}
+
+	/**
+	 * 任务处理组
+	 * 
+	 * @param groups
+	 */
+	public void setGroups(List<String> groups) {
+		this.groups = groups;
+	}
+
+	/**
+	 * 任务名称
+	 * 
+	 * @param taskId
+	 */
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+}

+ 192 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/ProcessDefinitionInfo.java

@@ -0,0 +1,192 @@
+package com.xtframe.core.wf;
+
+import java.util.Date;
+
+/**
+ * 流程定义对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class ProcessDefinitionInfo {
+    /** 流程定义ID */
+    private String processDefinitionId;
+    /** 流程发布ID */
+    private String deploymentId;
+    /** 名称 */
+    private String processName;
+    /** KEY */
+    private String key;
+    /** 流程版本号 */
+    private String version;
+    /** 部署时间 */
+    private Date deploymentTime;
+    /** 是否挂起 */
+    private Boolean suspended;
+    /** 流程定义文件名 */
+    private String resourceName;
+    /** 流程图名 */
+    private String diagramResourceName;
+
+    /**
+     * 流程发布ID
+     * 
+     * @return
+     */
+    public String getDeploymentId() {
+        return deploymentId;
+    }
+
+    /**
+     * 部署时间
+     * 
+     * @return
+     */
+    public Date getDeploymentTime() {
+        return deploymentTime;
+    }
+
+    /**
+     * 流程图名
+     * 
+     * @return
+     */
+    public String getDiagramResourceName() {
+        return diagramResourceName;
+    }
+
+    /**
+     * 流程定义KEY
+     * 
+     * @return
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * 流程定义ID
+     * 
+     * @return
+     */
+    public String getProcessDefinitionId() {
+        return processDefinitionId;
+    }
+
+    /**
+     * 名称
+     * 
+     * @return
+     */
+    public String getProcessName() {
+        return processName;
+    }
+
+    /**
+     * 流程定义文件名
+     * 
+     * @return
+     */
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    /**
+     * 是否挂起
+     * 
+     * @return
+     */
+    public Boolean getSuspended() {
+        return suspended;
+    }
+
+    /**
+     * 流程版本号
+     * 
+     * @return
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * 流程发布ID
+     * 
+     * @param deploymentId
+     */
+    public void setDeploymentId(String deploymentId) {
+        this.deploymentId = deploymentId;
+    }
+
+    /**
+     * 部署时间
+     * 
+     * @param deploymentTime
+     */
+    public void setDeploymentTime(Date deploymentTime) {
+        this.deploymentTime = deploymentTime;
+    }
+
+    /**
+     * 流程图名
+     * 
+     * @param diagramResourceName
+     */
+    public void setDiagramResourceName(String diagramResourceName) {
+        this.diagramResourceName = diagramResourceName;
+    }
+
+    /**
+     * 流程定义KEY
+     * 
+     * @param key
+     */
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    /**
+     * 流程定义ID
+     * 
+     * @param processDefinitionId
+     */
+    public void setProcessDefinitionId(String processDefinitionId) {
+        this.processDefinitionId = processDefinitionId;
+    }
+
+    /**
+     * 名称
+     * 
+     * @param processName
+     */
+    public void setProcessName(String processName) {
+        this.processName = processName;
+    }
+
+    /**
+     * 流程定义文件名
+     * 
+     * @param resourceName
+     */
+    public void setResourceName(String resourceName) {
+        this.resourceName = resourceName;
+    }
+
+    /**
+     * 是否挂起
+     * 
+     * @param suspended
+     */
+    public void setSuspended(Boolean suspended) {
+        this.suspended = suspended;
+    }
+
+    /**
+     * 流程版本号
+     * 
+     * @param version
+     */
+    public void setVersion(String version) {
+        this.version = version;
+    }
+}

+ 63 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/ProcessInst.java

@@ -0,0 +1,63 @@
+package com.xtframe.core.wf;
+
+import java.util.Map;
+
+/**
+ * 流程实例对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class ProcessInst extends Execution {
+
+    /**
+     * The id of the process definition of the process instance.
+     */
+    String processDefinitionId;
+
+    /**
+     * The business key of this process instance.
+     */
+    String bizKey;
+
+    /**
+     * returns true if the process instance is suspended
+     */
+    boolean suspended;
+
+    /** Returns the process variables if requested in the process instance query */
+    Map<String, Object> processVariables;
+
+    public String getBizKey() {
+        return bizKey;
+    }
+
+    public String getProcessDefinitionId() {
+        return processDefinitionId;
+    }
+
+    public Map<String, Object> getProcessVariables() {
+        return processVariables;
+    }
+
+    public boolean isSuspended() {
+        return suspended;
+    }
+
+    public void setBizKey(String bizKey) {
+        this.bizKey = bizKey;
+    }
+
+    public void setProcessDefinitionId(String processDefinitionId) {
+        this.processDefinitionId = processDefinitionId;
+    }
+
+    public void setProcessVariables(Map<String, Object> processVariables) {
+        this.processVariables = processVariables;
+    }
+
+    public void setSuspended(boolean suspended) {
+        this.suspended = suspended;
+    }
+
+}

+ 161 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/StepNode.java

@@ -0,0 +1,161 @@
+/** 
+ * 文 件 名 : StepNode.java 
+ * 创 建 人:袁晓冬
+ * 日     期: 2015年7月2日上午10:44:59
+ * 修 改 人: 
+ * 日     期: 
+ * 版 本 号: 
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司
+ */
+package com.xtframe.core.wf;
+
+import java.util.Date;
+
+/**
+ * CopyRright (c) 2015 江苏省新通智能交通科技发展有限公司<br/>
+ * 项 目 名: xtCore-oa<br/>
+ * 注 释: 流程步骤信息,用于退回时显示历史步骤列表 <br/>
+ * 命名空间: com.xtframe.core.wf<br/>
+ * 创 建 人: 袁晓冬<br/>
+ * 日 期: 2015年7月2日上午10:44:59<br/>
+ * 修 改 人:<br/>
+ * 日 期:<br/>
+ * 修改原因:<br/>
+ * 版 本 号:<br/>
+ * 
+ * @since JDK 1.6
+ */
+public class StepNode {
+    /** 流程Key */
+    private String processKey;
+    /** 流程步骤Key */
+    private String taskKey;
+    /** 步骤名称 */
+    private String taskName;
+    /** 步骤执行人ID */
+    private String[] handlerIds;
+    /** 步骤执行人名称 */
+    private String[] handlerNames;
+    /** 步骤开始时间 */
+    private Date kssj;
+    /** 步骤结束时间 */
+    private Date jssj;
+
+    /**
+     * 步骤执行人ID
+     * @return
+     */
+    public String[] getHandlerIds() {
+        return handlerIds;
+    }
+
+    /**
+     * 步骤执行人名称
+     * @return
+     */
+    public String[] getHandlerNames() {
+        return handlerNames;
+    }
+
+    /**
+     * 步骤结束时间
+     * 
+     * @return
+     */
+    public Date getJssj() {
+        return jssj;
+    }
+
+    /**
+     * 步骤开始时间
+     * 
+     * @return
+     */
+    public Date getKssj() {
+        return kssj;
+    }
+
+    /**
+     * 流程Key
+     * 
+     * @return
+     */
+    public String getProcessKey() {
+        return processKey;
+    }
+
+    /**
+     * 流程步骤Key
+     * @return
+     */
+    public String getTaskKey() {
+        return taskKey;
+    }
+
+    /**
+     * 步骤名称
+     * @return
+     */
+    public String getTaskName() {
+        return taskName;
+    }
+
+    /**
+     * 步骤执行人ID
+     * @param handlerIds
+     */
+    public void setHandlerIds(String[] handlerIds) {
+        this.handlerIds = handlerIds;
+    }
+
+    /**
+     * 步骤执行人名称
+     * @param handlerNames
+     */
+    public void setHandlerNames(String[] handlerNames) {
+        this.handlerNames = handlerNames;
+    }
+
+    /**
+     * 步骤结束时间
+     * 
+     * @param jssj
+     */
+    public void setJssj(Date jssj) {
+        this.jssj = jssj;
+    }
+
+    /**
+     * 步骤开始时间
+     * 
+     * @param kssj
+     */
+    public void setKssj(Date kssj) {
+        this.kssj = kssj;
+    }
+
+    /**
+     * 流程Key
+     * 
+     * @param processKey
+     */
+    public void setProcessKey(String processKey) {
+        this.processKey = processKey;
+    }
+
+    /**
+     * 流程步骤Key
+     * @param taskKey
+     */
+    public void setTaskKey(String taskKey) {
+        this.taskKey = taskKey;
+    }
+
+    /**
+     * 步骤名称
+     * @param taskName
+     */
+    public void setTaskName(String taskName) {
+        this.taskName = taskName;
+    }
+}

+ 220 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/SubmitInfo.java

@@ -0,0 +1,220 @@
+package com.xtframe.core.wf;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.xtframe.core.utils.WorkflowConsts;
+
+/**
+ * 活动完成提交信息
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class SubmitInfo {
+	/** 任务ID */
+	String taskId;
+	/** 当前处理人ID */
+	String currUserId;
+	/** 下一步步骤 */
+	String nextStep;
+	/** 流程业务信息,对流程的业务信息进行修改,同样的会反映到流程相关的待办事宜上。 */
+	String bizName;
+	/** 是否回退 */
+	boolean back = false;
+	/** 下一步处理人 */
+	List<String> handlers;
+	/** 活动数据,如果为空,则不更新 */
+	Map<String, Object> variables;
+	/** 任务变量 */
+	Map<String, Object> taskVariables;
+	/** 处理结果 */
+	String handleResult;
+	/** 处理意见 */
+	String handleRemark;
+
+	/**
+	 * 获取流程业务信息,对流程的业务信息进行修改,同样的会反映到流程相关的待办事宜上。
+	 * 
+	 * @return
+	 */
+	public String getBizName() {
+		return bizName;
+	}
+
+	/**
+	 * 获取当前处理人ID
+	 * 
+	 * @return
+	 */
+	public String getCurrUserId() {
+		return currUserId;
+	}
+
+	/**
+	 * 处理意见,审批时设置
+	 * 
+	 * @return
+	 */
+	public String getHandleRemark() {
+		return handleRemark;
+	}
+
+	/**
+	 * 处理结果,审批时设置通过/不通过
+	 * 
+	 * @return
+	 */
+	public String getHandleResult() {
+		return handleResult;
+	}
+
+	/**
+	 * 下一步处理人
+	 * 
+	 * @return
+	 */
+	public List<String> getHandlers() {
+		return handlers;
+	}
+
+	/**
+	 * 下一步步骤
+	 * 
+	 * @return
+	 */
+	public String getNextStep() {
+		return nextStep;
+	}
+
+	/**
+	 * 获取任务ID
+	 * 
+	 * @return
+	 */
+	public String getTaskId() {
+		return taskId;
+	}
+
+	/**
+	 * task变量,task变量只有在任务存在的时候才会设置,只设置到当前任务,不设置到下一步产生的任务中
+	 * 
+	 * @return
+	 */
+	public Map<String, Object> getTaskVariables() {
+		if (null == taskVariables) {
+			taskVariables = new HashMap<String, Object>();
+		}
+		return taskVariables;
+	}
+
+	/**
+	 * 获取流程变量
+	 * 
+	 * @return
+	 */
+	public Map<String, Object> getVariables() {
+		if (null == variables) {
+			variables = new HashMap<String, Object>();
+		}
+		return variables;
+	}
+
+	public boolean isBack() {
+		return back;
+	}
+
+	public void setBack(boolean back) {
+		this.back = back;
+	}
+
+	/**
+	 * 设置流程业务信息,对流程的业务信息进行修改,同样的会反映到流程相关的待办事宜上。
+	 * 
+	 * @param bizName
+	 */
+	public void setBizName(String bizName) {
+		this.bizName = bizName;
+		getVariables().put(WorkflowConsts.WF_BIZ_NAME, bizName);
+	}
+
+	/**
+	 * 设置当前处理人ID
+	 * 
+	 * @param currUserId
+	 */
+	public void setCurrUserId(String currUserId) {
+		this.currUserId = currUserId;
+	}
+
+	/**
+	 * 处理意见,审批时设置
+	 * 
+	 * @param handleRemark
+	 */
+	public void setHandleRemark(String handleRemark) {
+		this.handleRemark = handleRemark;
+		getTaskVariables().put(WorkflowConsts.WF_HANDLER_REMARK, handleRemark);
+	}
+
+	/**
+	 * 处理结果,审批时设置通过/不通过
+	 * 
+	 * @param handleResult
+	 */
+	public void setHandleResult(String handleResult) {
+		this.handleResult = handleResult;
+		getTaskVariables().put(WorkflowConsts.WF_HANDLER_RESULT, handleResult);
+	}
+
+	/**
+	 * 下一步处理人
+	 * 
+	 * @param handlers
+	 */
+	public void setHandlers(List<String> handlers) {
+		getVariables().put(WorkflowConsts.WF_BIZ_HANDLERS, handlers);
+		this.handlers = handlers;
+	}
+
+	/**
+	 * 下一步步骤
+	 * 
+	 * @param nextStep
+	 */
+	public void setNextStep(String nextStep) {
+		getVariables().put(WorkflowConsts.WF_BIZ_NEXT_STEP, nextStep);
+		this.nextStep = nextStep;
+	}
+
+	/**
+	 * 设置任务ID
+	 * 
+	 * @param taskId
+	 */
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+
+	/**
+	 * task变量
+	 * 
+	 * @param taskVariables
+	 * @deprecated 一般get之后put变量
+	 */
+	@Deprecated
+	public void setTaskVariables(Map<String, Object> taskVariables) {
+		this.taskVariables = taskVariables;
+	}
+
+	/**
+	 * 设置流程变量
+	 * 
+	 * @param variables
+	 */
+	public void setVariables(Map<String, Object> variables) {
+		this.variables = variables;
+	}
+
+}

+ 196 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/TaskNode.java

@@ -0,0 +1,196 @@
+package com.xtframe.core.wf;
+
+import java.util.List;
+
+/**
+ * 流程节点信息
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class TaskNode {
+    /** 流程Key */
+    private String processKey;
+    /** 任务Key */
+    private String taskKey;
+    /** 流程步骤配置ID */
+    private String stepId;
+    /** 步骤名称 */
+    private String taskName;
+    /** 是否默认 */
+    private Boolean sfmr;
+    /** 执行角色 */
+    private List<String> roles;
+    /** 是否最后一个任务 */
+    private Boolean lastTask;
+
+    /** 执行用户 */
+    private List<String> users;
+
+    /** 执行组织 */
+    private List<String> orgs;
+
+    /** 任务执行人ID */
+    private String[] handlerIds;
+
+    /** 任务执行人名称 */
+    private String[] handlerNames;
+
+    /**
+     * 任务执行人ID【回退时有】
+     * 
+     * @return
+     */
+    public String[] getHandlerIds() {
+        return handlerIds;
+    }
+
+    /**
+     * 任务执行人名称【回退时有】
+     * 
+     * @return
+     */
+    public String[] getHandlerNames() {
+        return handlerNames;
+    }
+
+    /**
+     * 是否最后一个任务
+     * 
+     * @return
+     */
+    public Boolean getLastTask() {
+        return lastTask;
+    }
+
+    /**
+     * 执行组织
+     * 
+     * @return
+     */
+    public List<String> getOrgs() {
+        return orgs;
+    }
+
+    /**
+     * 流程key
+     * 
+     * @return
+     */
+    public String getProcessKey() {
+        return processKey;
+    }
+
+    /**
+     * 任务执行角色
+     * 
+     * @return
+     */
+    public List<String> getRoles() {
+        return roles;
+    }
+
+    /**
+     * 是否默认
+     * 
+     * @return
+     */
+    public Boolean getSfmr() {
+        return sfmr;
+    }
+
+    /**
+     * 流程步骤配置ID
+     * 
+     * @return
+     */
+    public String getStepId() {
+        return stepId;
+    }
+
+    /**
+     * 任务Key
+     * 
+     * @return
+     */
+    public String getTaskKey() {
+        return taskKey;
+    }
+
+    /**
+     * 步骤名称
+     * 
+     * @return
+     */
+    public String getTaskName() {
+        return taskName;
+    }
+
+    public List<String> getUsers() {
+        return users;
+    }
+
+    public void setHandlerIds(String[] handlerIds) {
+        this.handlerIds = handlerIds;
+    }
+
+    public void setHandlerNames(String[] handlerNames) {
+        this.handlerNames = handlerNames;
+    }
+
+    /**
+     * 是否最后一个任务
+     * 
+     * @param lastTask
+     */
+    public void setLastTask(Boolean lastTask) {
+        this.lastTask = lastTask;
+    }
+
+    public void setOrgs(List<String> orgs) {
+        this.orgs = orgs;
+    }
+
+    public void setProcessKey(String processKey) {
+        this.processKey = processKey;
+    }
+
+    public void setRoles(List<String> roles) {
+        this.roles = roles;
+    }
+
+    /**
+     * 是否默认
+     * 
+     * @param sfmr
+     */
+    public void setSfmr(Boolean sfmr) {
+        this.sfmr = sfmr;
+    }
+
+    /**
+     * 流程步骤配置ID
+     * 
+     * @param stepId
+     */
+    public void setStepId(String stepId) {
+        this.stepId = stepId;
+    }
+
+    public void setTaskKey(String taskKey) {
+        this.taskKey = taskKey;
+    }
+
+    /**
+     * 步骤名称
+     * 
+     * @param name
+     */
+    public void setTaskName(String name) {
+        this.taskName = name;
+    }
+
+    public void setUsers(List<String> users) {
+        this.users = users;
+    }
+}

+ 213 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WFStartInfo.java

@@ -0,0 +1,213 @@
+package com.xtframe.core.wf;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.xtframe.core.utils.WorkflowConsts;
+import com.xtframe.util.StringUtils;
+
+/**
+ * 流程启动信息
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class WFStartInfo {
+    /** 业务系统发起 */
+    public static final int STARTTYPE_COMMON = 1;
+    /** BPM发起 */
+    public static final int STARTTYPE_BPM = 0;
+    /** 流程Code(必填) */
+    String processDefinitionKey;
+    /** 流程发起人ID(必填) */
+    String startUserId;
+    /** 业务key */
+    String businessKey;
+    /** 流程发起人组织角色ID(必填) */
+    String roleId;
+    /** 启动类型,参见WFStartInfo的静态变量,默认为WFStartInfo.STARTTYPE_COMMON */
+    int startType;
+    /** 业务名称,在待办事宜中显示 */
+    String bizName;
+    /** 下一步步骤 */
+    String nextStep;
+    /** 下一步处理人 */
+    List<String> handlers;
+    /** 流程变量 */
+    Map<String, Object> variables;
+    /** 任务变量 */
+    Map<String, Object> taskVariables;
+    
+    /**
+     * 获取流程实例名称
+     * 
+     * @return
+     */
+    public String getBizName() {
+        return bizName;
+    }
+
+    /**
+     * 获取业务主键
+     * 
+     * @return
+     */
+    public String getBusinessKey() {
+        return businessKey;
+    }
+
+    /**
+     * 下一步处理人
+     * 
+     * @return
+     */
+    public List<String> getHandlers() {
+        return handlers;
+    }
+
+    /**
+     * 下一步步骤
+     * 
+     * @return
+     */
+    public String getNextStep() {
+        return nextStep;
+    }
+
+    /**
+     * 获取流程定义主键
+     * 
+     * @return
+     */
+    public String getProcessDefinitionKey() {
+        return processDefinitionKey;
+    }
+
+    /**
+     * 获取执行人角色
+     * 
+     * @return
+     */
+    public String getRoleId() {
+        return roleId;
+    }
+
+    /**
+     * 获取流程启动类型
+     * 
+     * @return
+     */
+    public int getStartType() {
+        return startType;
+    }
+
+    /**
+     * 获取当前执行人ID
+     * 
+     * @return
+     */
+    public String getStartUserId() {
+        return StringUtils.toNotNullString(getVariables().put(WorkflowConsts.WF_SENDER_ID, startUserId));
+    }
+
+    public Map<String, Object> getTaskVariables() {
+        if (null == taskVariables) {
+            taskVariables = new HashMap<String, Object>();
+        }
+        return taskVariables;
+    }
+
+    /**
+     * 获取流程变量,如果为null则自动创建
+     * 
+     * @return
+     */
+    public Map<String, Object> getVariables() {
+        if (null == variables) {
+            variables = new HashMap<String, Object>();
+            variables.put(WorkflowConsts.WF_START_TYPE, STARTTYPE_COMMON);
+        }
+        return variables;
+    }
+
+    /**
+     * 设置流程业务名称,同时会加入流程变量variables.s_biz_name中
+     * 
+     * @param bizName
+     */
+    public void setBizName(String bizName) {
+        this.bizName = bizName;
+        getVariables().put(WorkflowConsts.WF_BIZ_NAME, bizName);
+    }
+
+    public void setBusinessKey(String businessKey) {
+        this.businessKey = businessKey;
+    }
+
+    /**
+     * 下一步处理人
+     * 
+     * @param handlers
+     */
+    public void setHandlers(List<String> handlers) {
+        this.handlers = handlers;
+    }
+
+    /**
+     * 下一步步骤
+     * 
+     * @param nextStep
+     */
+    public void setNextStep(String nextStep) {
+        this.nextStep = nextStep;
+    }
+
+    public void setProcessDefinitionKey(String processDefinitionKey) {
+        this.processDefinitionKey = processDefinitionKey;
+    }
+
+    /**
+     * 设置角色ID,同时会加入流程变量variables.s_roleId中
+     * 
+     * @param roleId
+     */
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+        getVariables().put(WorkflowConsts.WF_ROLE_ID, roleId);
+    }
+
+    /**
+     * 设置流程启动类型,同时会加入流程变量variables.s_startType中
+     * 
+     * @param startType
+     */
+    public void setStartType(int startType) {
+        this.startType = startType;
+        getVariables().put(WorkflowConsts.WF_START_TYPE, startType);
+    }
+
+    /**
+     * 设置流程执行人ID,同时会加入流程变量variables.s_sender_id中
+     * 
+     * @param userId
+     */
+    public void setStartUserId(String userId) {
+        this.startUserId = userId;
+        getVariables().put(WorkflowConsts.WF_SENDER_ID, userId);
+    }
+
+    public void setTaskVariables(Map<String, Object> taskVariables) {
+        this.taskVariables = taskVariables;
+    }
+
+    /**
+     * 设置流程变量,一般使用getVariables之后再put具体属性
+     * 
+     * @param variables
+     */
+    @Deprecated
+    public void setVariables(Map<String, Object> variables) {
+        this.variables = variables;
+    }
+}

+ 66 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WfResult.java

@@ -0,0 +1,66 @@
+package com.xtframe.core.wf;
+
+import java.util.List;
+
+/**
+ * 流程执行结果对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class WfResult {
+	/** 流程实例ID */
+	long workflowInstanceId;
+	/** 流程发起人参与的手工活动处理的待办事宜URL */
+	String[] url;
+	/** 后续活动及处理人信息 */
+	List<NextTask> nextInfo;
+
+	/**
+	 * 后续活动及处理人信息
+	 * @return List<NextTask>
+	 */
+	public List<NextTask> getNextInfo() {
+		return nextInfo;
+	}
+
+	/**
+	 * 流程发起人参与的手工活动处理的待办事宜URL
+	 * @return
+	 */
+	public String[] getUrl() {
+		return url;
+	}
+
+	/**
+	 * 流程实例ID
+	 * @return
+	 */
+	public long getWorkflowInstanceId() {
+		return workflowInstanceId;
+	}
+
+	/**
+	 * 后续活动及处理人信息
+	 * @param nextInfo
+	 */
+	public void setNextInfo(List<NextTask> nextInfo) {
+		this.nextInfo = nextInfo;
+	}
+
+	/**
+	 * 流程发起人参与的手工活动处理的待办事宜URL
+	 * @param url
+	 */
+	public void setUrl(String[] url) {
+		this.url = url;
+	}
+
+	/**
+	 * 流程实例ID
+	 * @param workflowInstanceId
+	 */
+	public void setWorkflowInstanceId(long workflowInstanceId) {
+		this.workflowInstanceId = workflowInstanceId;
+	}
+}

+ 406 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WorkFlowEngineClient.java

@@ -0,0 +1,406 @@
+package com.xtframe.core.wf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+import com.xtframe.core.user.entity.User;
+import com.xtframe.core.utils.WorkflowConsts;
+
+/**
+ * 流程引擎客户端
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface WorkFlowEngineClient {
+    /** 流程结束点 */
+    String ACT_END = "_end";
+
+    /**
+     * 签收处理
+     * 
+     * @param taskId
+     * @param userId
+     */
+    public void claim(String taskId, String userId);
+
+    /**
+     * 完成一个手工活动,并指定下一步活动、处理人。
+     * 
+     * @param submitInfo
+     *            活动完成提交信息(必填)
+     * @return 后续活动及处理人信息
+     */
+    public WfResult complete(SubmitInfo submitInfo);
+
+    /**
+     * 完成任务,并指定是否使用跳转
+     * 
+     * @param submitInfo
+     * @param jump
+     *            跳转:true;正常完成:false
+     * @return
+     */
+    public WfResult complete(SubmitInfo submitInfo, boolean jump);
+
+    /**
+     * 根据流程启动信息发起流程
+     * 
+     * @param stInfo
+     *            流程启动信息
+     * @return ProcessInst 流程实例对象
+     */
+    public ProcessInst create(WFStartInfo info);
+
+    /**
+     * 创建流程并完成第一步
+     * 
+     * @param info
+     * @return
+     */
+    public ProcessInst createAndFinishFirstStep(WFStartInfo info);
+
+    /**
+     * 删除部署的流程
+     * 
+     * @param deploymentId
+     *            流程部署ID
+     * @param cascade
+     *            是否级联删除流程实例
+     */
+    public void deleteDeployment(String deploymentId, boolean cascade);
+
+    /**
+     * 结束流程
+     * 
+     * @param taskId
+     * @return
+     */
+    public boolean endProcess(String taskId, Map<String, Object> taskVariables);
+
+    /**
+     * 根据任务ID和节点ID获取活动节点 <br>
+     * 
+     * @param taskId
+     *            任务ID
+     * @param activityId
+     *            活动节点ID <br>
+     *            如果为null或"",则默认查询当前活动节点 <br>
+     *            如果为"end",则查询结束节点 <br>
+     * 
+     * @return
+     * @throws Exception
+     */
+    public Object findActivitiImpl(String taskId, String activityId);
+
+    /**
+     * 查询当前任务可以驳回的流程节点
+     * 
+     * @param taskId
+     * @return
+     */
+    @Deprecated
+    public List<TaskNode> findBackNodes(String taskId);
+
+    /**
+     * 根据任务ID查找历史步骤信息
+     * 
+     * @param taskId
+     *            流程任意任务ID
+     * @param bussKey
+     *            业务Key
+     * @return
+     */
+    public List<StepNode> findHistoryStepNodes(String taskId, String bussKey);
+
+    /**
+     * 根据流程步骤和流程ID获取可驳回的流程节点,用于流程配置画面
+     * 
+     * @param activity
+     * @param wfid
+     * @return
+     */
+    public List<TaskNode> findBackNodesByActivity(String activity, String wfid);
+
+    /**
+     * 获取可跳转节点
+     * 
+     * @param taskId
+     *            任务ID
+     * @param wfid
+     *            流程ID
+     * @return
+     */
+    public List<TaskNode> findNextNodes(TaskNode node);
+
+    /**
+     * 根据流程步骤和流程ID获取可跳转节点,用于流程配置画面
+     * 
+     * @param activity
+     * @param wfid
+     * @return
+     * @deprecated 使用findProcessSteps(wfKey)
+     */
+    @Deprecated
+    public List<TaskNode> findJumpNodesByActivity(String activity, String wfid);
+
+    /***
+     * 根据组织编码和角色编码查找角色。<br>
+     * 组织编码为{@link WorkflowConsts#WF_UEL_PARAM_CURR_ORG} 时取用户当前所在组织的编码
+     * 
+     * @param code
+     * @param org
+     * @return
+     */
+    public List<String> findRoleByCodeAndOrgCode(String code, String orgCode);
+
+    /**
+     * 根据角色编码和上级组织编码查找角色(不包含本级组织)。<br>
+     * 组织编码为{@link WorkflowConsts#WF_UEL_PARAM_CURR_ORG} 时取用户当前所在组织的编码
+     * 
+     * @param code
+     * @param org
+     * @return
+     */
+    public List<String> findRoleByCodeAndPOrgCode(String code, String orgCode);
+
+    /**
+     * 根据角色编码查找指定组织的上级组织编码(不包含本级组织)。<br>
+     * 组织编码为{@link WorkflowConsts#WF_UEL_PARAM_CURR_ORG} 时取用户当前所在组织的编码
+     * 
+     * @param code
+     * @param org
+     * @return
+     */
+    public List<String> findRoleByCodeAndSubOrgCode(String code, String orgCode);
+
+    /**
+     * 根据组织编码查找角色。<br>
+     * 组织编码为{@link WorkflowConsts#WF_UEL_PARAM_CURR_ORG} 时取用户当前所在组织的编码
+     * 
+     * @param org
+     * @return
+     */
+    public List<String> findRoleByOrgCode(String orgCode);
+
+    /**
+     * 根据组织编码查找用户
+     * 
+     * @param orgCode
+     * @return
+     */
+    public List<String> findUserByOrgCode(String orgCode);
+
+    /**
+     * 根据业务主键查询流程变量
+     * 
+     * @param bussKey
+     * @return
+     */
+    public Map<String, Object> getProcessVariables(String bussKey);
+
+    /**
+     * 根据任务ID获取节点信息
+     * 
+     * @param taskId
+     * @return
+     */
+    public TaskNode findTaskNodeByTaskId(String taskId);
+
+    /**
+     * 流程跳转
+     * 
+     * @param taskId
+     *            任务ID
+     * @param activityId
+     *            流程步骤
+     * @return
+     */
+    public boolean jump(String taskId, String activityId, Map<String, Object> variables,
+            Map<String, Object> taskVariables);
+
+    /**
+     * 通过部署ID读取资源
+     * 
+     * @param processDefinitionId
+     *            部署ID
+     * @param resourceType
+     *            资源类型,image\xml...
+     * @param out
+     *            输出流
+     */
+    public void loadByDeployment(String processDefinitionId, String resourceType, OutputStream out) throws IOException;
+
+    /**
+     * 读取资源,通过流程ID
+     *
+     * @param resourceType
+     *            资源类型(xml|image)
+     * @param processInstanceId
+     *            流程实例ID
+     * @param response
+     * @throws Exception
+     */
+    public void loadByProcessInstance(String processInstanceId, String resourceType, OutputStream out) throws Exception;
+
+    /**
+     * 根据任务ID查找流程步骤,用于流程跳转时步骤查询
+     * 
+     * @param taskId
+     *            任务ID
+     * @return List<String>
+     */
+    public List<String> queryActivityIds(String taskId);
+
+    /**
+     * 根据业务主键查询历史工作记录
+     * 
+     * @param bussKey
+     * @return
+     */
+    public List<WorkItem> queryHistoryWorkItemInfo(String bussKey);
+
+    /**
+     * 分页检索流程定义
+     * 
+     * @param cntPerPage
+     *            每页条数
+     * @param currPage
+     *            当前页
+     * @param processDefinition
+     *            接收结果集合
+     * @return
+     */
+    public long queryProcessDefinition(int cntPerPage, int currPage, List<ProcessDefinitionInfo> processDefinition);
+
+    /**
+     * 分页查询流程实例
+     * 
+     * @param cntPerPage
+     *            每页条数
+     * @param currPage
+     *            当前页
+     * @param processDefinition
+     *            接收结果集合
+     * @return
+     */
+    public long queryProcessInstance(int cntPerPage, int currPage, List<ProcessInst> processInsts);
+
+    /**
+     * 根据业务主键和任务处理人(可选)查询工作记录
+     * 
+     * @param bussKey
+     *            业务主键,必填
+     * @param assignee
+     *            处理人,可空
+     * @return
+     */
+    public List<WorkItem> queryWorkItemInfo(String bussKey, String assignee);
+
+    /**
+     * 工作项查询接口
+     * 
+     * @param userId
+     *            用户ID(必填)
+     * @param workFlowCode
+     *            流程编码(为空时查询所有流程)
+     * @param state
+     *            0:所有的 1:待办事宜 2:已办事宜
+     * @param cntPerPage
+     *            分页参数:每页显示多少条,即当前返回记录条数 如果为0,则不分页,返回所有记录
+     * @param currPage
+     *            分页参数:显示第几页记录。 如果为0,则显示第一页
+     * @return
+     */
+    public long queryWorkItemInfo(String userId, String workFlowCode, int state, int cntPerPage, int currPage,
+            List<WorkItem> items);
+
+    /**
+     * 工作项查询接口
+     * 
+     * @param userId
+     *            用户ID(必填)
+     * @param workFlowCodes
+     *            流程编码(必填)
+     * @param state
+     *            0:所有的 1:待办事宜 2:已办事宜
+     * @param cntPerPage
+     *            分页参数:每页显示多少条,即当前返回记录条数 如果为0,则不分页,返回所有记录
+     * @param currPage
+     *            分页参数:显示第几页记录。 如果为0,则显示第一页
+     * @return
+     */
+    public long queryWorkItemInfoByWfkeys(String userId, String[] workFlowCodes, int state, int cntPerPage,
+            int currPage, List<WorkItem> items);
+
+    /**
+     * 读取带跟踪的图片
+     * 
+     * @param executionId
+     * @param out
+     * @throws Exception
+     */
+    public void readResource(String executionId, OutputStream out) throws Exception;
+
+    /**
+     * 输出跟踪流程信息
+     * 
+     * @param processInstanceId
+     * @return
+     * @throws Exception
+     */
+    public List<Map<String, Object>> traceProcess(String processInstanceId) throws Exception;
+
+    /**
+     * 转办任务
+     * 
+     * @param taskId
+     *            当前任务节点ID
+     * @param userId
+     *            被转办人
+     */
+    public void transferTask(String taskId, String userId);
+
+    /**
+     * 更新流程实例状态
+     * 
+     * @param state
+     * @param processDefinitionId
+     */
+    public void updateInstanceState(String state, String processInstanceId);
+
+    /**
+     * 设置流程状态<br>
+     * <li>active 激活已挂起的流程 <li>suspend 挂起已激活的流程
+     * 
+     * @param state
+     * @param processDefinitionId
+     *            流程定义ID
+     * @return
+     */
+    public void updateProcessState(String state, String processDefinitionId);
+
+    @Deprecated
+    List<TaskNode> findJumpNodes(String taskId, String wfid);
+
+    public List<User> findUserByStepId(String stepId);
+
+    /**
+     * 根据taskId判断流程是否已经结束
+     * 
+     * @param taskId
+     * @return
+     */
+    public boolean isProcessEnded(String taskId);
+
+    /**
+     * 根据流程定义key查询流程定义所有步骤信息
+     * 
+     * @param wfKey
+     *            流程定义key
+     * @return
+     */
+    public List<TaskNode> findProcessSteps(String wfKey);
+}

+ 375 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-core/src/main/java/com/xtframe/core/wf/WorkItem.java

@@ -0,0 +1,375 @@
+package com.xtframe.core.wf;
+
+import java.util.Date;
+
+/**
+ * 工作项
+ * 
+ * @author 袁晓冬
+ * 
+ */
+public class WorkItem {
+    /** 任务ID */
+    String taskId;
+    /** 页面处理url */
+    String url;
+    /** 历史事宜查看url */
+    String viewUrl;
+    /** 业务ID */
+    String bizKey;
+    /** 业务名称,在待办事宜中显示 */
+    String bizName;
+    /** 流程/实例名称 */
+    String processName;
+    /** 步骤名称 */
+    String stepName;
+    /** 处理人ID */
+    String assignee;
+    /** 处理人名称 */
+    String assigneeName;
+    /** 处理结果,一般历史任务中有 */
+    String handleResult;
+    /** 处理意见,一般历史任务中有 */
+    String handleRemark;
+    /** 发送人ID */
+    String senderId;
+    /** 发送人名称 */
+    String senderName;
+    /** 发送人组织角色 */
+    String senderRoleId;
+    /** 发送人所在组织ID */
+    String senderOrgId;
+    /** 发送人所在组织名称 */
+    String senderOrgName;
+    /** 发送时间 */
+    Date senderTime;
+    /** 是否签收状态 */
+    boolean claim;
+
+    /**
+     * 处理人ID
+     * 
+     * @return
+     */
+    public String getAssignee() {
+        return assignee;
+    }
+
+    /**
+     * 处理人名称
+     * 
+     * @return
+     */
+    public String getAssigneeName() {
+        return assigneeName;
+    }
+
+    /**
+     * 业务ID
+     * 
+     * @return
+     */
+    public String getBizKey() {
+        return bizKey;
+    }
+
+    /**
+     * 业务名称,在待办事宜中显示
+     * 
+     * @return
+     */
+    public String getBizName() {
+        return bizName;
+    }
+
+    /**
+     * 处理意见,一般历史任务中有
+     * 
+     * @return
+     */
+    public String getHandleRemark() {
+        return handleRemark;
+    }
+
+    /**
+     * 处理结果,一般历史任务中有
+     * 
+     * @return
+     */
+    public String getHandleResult() {
+        return handleResult;
+    }
+
+    /**
+     * 流程/实例名称
+     * 
+     * @return
+     */
+    public String getProcessName() {
+        return processName;
+    }
+
+    /**
+     * 发送人ID
+     * 
+     * @return
+     */
+    public String getSenderId() {
+        return senderId;
+    }
+
+    /**
+     * 发送人名称
+     * 
+     * @return
+     */
+    public String getSenderName() {
+        return senderName;
+    }
+
+    /**
+     * 发送人所在组织ID
+     * 
+     * @return
+     */
+    public String getSenderOrgId() {
+        return senderOrgId;
+    }
+
+    /**
+     * 发送人所在组织名称
+     * 
+     * @return
+     */
+    public String getSenderOrgName() {
+        return senderOrgName;
+    }
+
+    /**
+     * 发送人组织角色
+     * 
+     * @return
+     */
+    public String getSenderRoleId() {
+        return senderRoleId;
+    }
+
+    /**
+     * 发送时间
+     * 
+     * @return
+     */
+    public Date getSenderTime() {
+        return senderTime;
+    }
+
+    /**
+     * 步骤名称
+     * 
+     * @return
+     */
+    public String getStepName() {
+        return stepName;
+    }
+
+    /**
+     * 任务ID
+     * 
+     * @return
+     */
+    public String getTaskId() {
+        return taskId;
+    }
+
+    /**
+     * 页面处理url
+     * 
+     * @return
+     */
+    public String getUrl() {
+        return url;
+    }
+
+    /**
+     * 历史事宜查看url
+     * 
+     * @return
+     */
+    public String getViewUrl() {
+        return viewUrl;
+    }
+
+    /**
+     * 是否签收状态
+     * 
+     * @return
+     * @deprecated 不建议使用
+     */
+    public boolean isClaim() {
+        return claim;
+    }
+
+    /**
+     * 处理人ID
+     * 
+     * @param assignee
+     */
+    public void setAssignee(String assignee) {
+        this.assignee = assignee;
+    }
+
+    /**
+     * 处理人名称
+     * 
+     * @param assigneeName
+     */
+    public void setAssigneeName(String assigneeName) {
+        this.assigneeName = assigneeName;
+    }
+
+    /**
+     * 业务ID
+     * 
+     * @param bizKey
+     */
+    public void setBizKey(String bizKey) {
+        this.bizKey = bizKey;
+    }
+
+    /**
+     * 业务名称,在待办事宜中显示
+     * 
+     * @param bizName
+     */
+    public void setBizName(String bizName) {
+        this.bizName = bizName;
+    }
+
+    /**
+     * 是否签收状态
+     * 
+     * @param claim
+     * @deprecated 不建议使用,任务直接处理,不做签收步骤
+     */
+    public void setClaim(boolean claim) {
+        this.claim = claim;
+    }
+
+    /**
+     * 处理意见,一般历史任务中有
+     * 
+     * @param handleRemark
+     */
+    public void setHandleRemark(String handleRemark) {
+        this.handleRemark = handleRemark;
+    }
+
+    /**
+     * 处理结果,一般历史任务中有
+     * 
+     * @param handleResult
+     */
+    public void setHandleResult(String handleResult) {
+        this.handleResult = handleResult;
+    }
+
+    /**
+     * 流程/实例名称
+     * 
+     * @param processName
+     */
+    public void setProcessName(String processName) {
+        this.processName = processName;
+    }
+
+    /**
+     * 发送人ID
+     * 
+     * @param senderId
+     */
+    public void setSenderId(String senderId) {
+        this.senderId = senderId;
+    }
+
+    /**
+     * 发送人名称
+     * 
+     * @param senderName
+     */
+    public void setSenderName(String senderName) {
+        this.senderName = senderName;
+    }
+
+    /**
+     * 发送人所在组织ID
+     * 
+     * @param senderOrgId
+     */
+    public void setSenderOrgId(String senderOrgId) {
+        this.senderOrgId = senderOrgId;
+    }
+
+    /**
+     * 发送人所在组织名称
+     * 
+     * @param senderOrgName
+     */
+    public void setSenderOrgName(String senderOrgName) {
+        this.senderOrgName = senderOrgName;
+    }
+
+    /**
+     * 发送人组织角色
+     * 
+     * @param senderRoleId
+     */
+    public void setSenderRoleId(String senderRoleId) {
+        this.senderRoleId = senderRoleId;
+    }
+
+    /**
+     * 发送时间
+     * 
+     * @param senderTime
+     */
+    public void setSenderTime(Date senderTime) {
+        this.senderTime = senderTime;
+    }
+
+    /**
+     * 步骤名称
+     * 
+     * @param stepName
+     */
+    public void setStepName(String stepName) {
+        this.stepName = stepName;
+    }
+
+    /**
+     * 任务ID
+     * 
+     * @param taskId
+     */
+    public void setTaskId(String taskId) {
+        this.taskId = taskId;
+    }
+
+    /**
+     * 页面处理url
+     * 
+     * @param url
+     */
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /**
+     * 历史事宜查看url
+     * 
+     * @param viewUrl
+     */
+    public void setViewUrl(String viewUrl) {
+        this.viewUrl = viewUrl;
+    }
+
+}

+ 26 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/.classpath

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

+ 23 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/.project

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>xtIo-oa</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/<project>=UTF-8

+ 5 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7

+ 4 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/.settings/org.eclipse.m2e.core.prefs

@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

+ 13 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-io/pom.xml

@@ -0,0 +1,13 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.xtframe</groupId>
+        <artifactId>xtproject-oa</artifactId>
+        <version>0.1.3-SNAPSHOT</version>
+        <relativePath>../../</relativePath>
+    </parent>
+    <artifactId>xtIo-oa</artifactId>
+    <name>框架IO包</name>
+    <description>提供各种输入输出通用方法,如RTX接口、短信接口等</description>
+</project>

+ 31 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/.classpath

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

+ 29 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/.project

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>xtSecurity-oa</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.springframework.ide.eclipse.core.springbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.springframework.ide.eclipse.core.springnature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

+ 5 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8

+ 5 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7

+ 4 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/.settings/org.eclipse.m2e.core.prefs

@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

+ 109 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/pom.xml

@@ -0,0 +1,109 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.xtframe</groupId>
+		<artifactId>xtproject-oa</artifactId>
+		<version>0.1.3-SNAPSHOT</version>
+		<relativePath>../../</relativePath>
+	</parent>
+	<artifactId>xtSecurity-oa</artifactId>
+	<dependencies>
+		<dependency>
+			<groupId>com.xtframe</groupId>
+			<artifactId>xtCore-oa</artifactId>
+		</dependency>
+		<!-- SECURITY begin -->
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-cas</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-spring</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-ehcache</artifactId>
+		</dependency>
+		<!-- SECURITY end -->
+		<!-- spring -->
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.data</groupId>
+			<artifactId>spring-data-jpa</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>jstl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>taglibs</groupId>
+			<artifactId>standard</artifactId>
+		</dependency>
+		<!-- hibernate -->
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.hibernate</groupId>
+			<artifactId>hibernate-entitymanager</artifactId>
+		</dependency>
+		<!-- json -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-annotations</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.quartz-scheduler</groupId>
+			<artifactId>quartz</artifactId>
+			<version>2.2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>org.quartz-scheduler</groupId>
+			<artifactId>quartz-jobs</artifactId>
+			<version>2.2.1</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.json-lib</groupId>
+			<artifactId>json-lib</artifactId>
+			<version>2.4</version>
+			<classifier>jdk15</classifier>
+		</dependency>
+	</dependencies>
+	<name>框架安全包</name>
+	<description>提供框架核心用户、角色、组织等服务接口实现,提供权限管理</description>
+</project>

+ 1 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/readme

@@ -0,0 +1 @@
+基于shiro对core的一个实现,一览与spring data jpa

+ 87 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/dao/CodeDao.java

@@ -0,0 +1,87 @@
+package com.xtframe.sec.code.dao;
+
+import java.util.List;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Query;
+
+import com.xtframe.core.code.entity.Code;
+import com.xtframe.sec.code.entity.CodeEntity;
+import com.xtframe.sec.common.SecRepository;
+
+/**
+ * 编码Dao
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface CodeDao extends SecRepository<CodeEntity, String> {
+    /**
+     * 根据编码查找
+     * 
+     * @param code
+     * @return
+     */
+    public Code findByCode(String code);
+
+    /**
+     * 根据上级编码检索下级
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Code> findByPcode(String pcode);
+
+    /**
+     * 根据上级编码分页检索下级
+     * 
+     * @param pcode
+     * @param pageable
+     * @return
+     */
+    Page<Code> findByPcode(String pcode, Pageable pageable);
+
+    /**
+     * 根据上级编码ID查找下一级
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Code> findByPid(String pid);
+
+    /**
+     * 根据上级ID和是否有效查询下级字典,按sortno升序排序
+     * 
+     * @param pid
+     * @param valid
+     * @return
+     */
+    public List<Code> findByPidAndValidOrderBySortnoAsc(String pid, boolean valid);
+
+    /**
+     * 根据上级编码ID分页查找下一级
+     * 
+     * @param pid
+     * @param pageable
+     * @return
+     */
+    public Page<Code> findByPid(String pid, Pageable pageable);
+
+    /**
+     * 根据上级ID和是否有效查询字典
+     * 
+     * @param pid
+     * @param pageable
+     * @return
+     */
+    public Page<Code> findByPidAndValid(String pid, boolean valid, Pageable pageable);
+
+    /**
+     * 
+     * @param pid
+     * @return
+     */
+    @Query("SELECT m FROM CodeEntity m  WHERE m.pid =?1 and m.valid='Y'")
+    public List<Code> findValidCodesByPid(String pid);
+}

+ 185 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/entity/CodeEntity.java

@@ -0,0 +1,185 @@
+package com.xtframe.sec.code.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xtframe.core.code.entity.Code;
+import com.xtframe.sec.common.BaseEntity;
+import com.xtframe.sec.utils.BooleanSerializer;
+
+/**
+ * 字典数据实体
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Entity
+@Table(name = "t_xtframe_code")
+public class CodeEntity extends BaseEntity<String> implements Code {
+    /** serialVersionUID */
+    private static final long serialVersionUID = 7613063990222722958L;
+    /** UUID */
+    private String id;
+    /** 上级UUID */
+    private String pid;
+    /** 上级编码 */
+    private String pcode;
+    /** 编码 */
+    private String text;
+    /** 编码 */
+    private String code;
+    /** 是否有效 */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean leaf;
+    /** 是否有效 */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean valid = true;
+    /** 排序号 */
+    private int sortno;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#getCode()
+     */
+    @Override
+    public String getCode() {
+        return code;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#getId()
+     */
+    @Override
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getLeaf() {
+        return leaf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#getPcode()
+     */
+    @Override
+    public String getPcode() {
+        return pcode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#getPid()
+     */
+    @Override
+    public String getPid() {
+        return pid;
+    }
+
+    /**
+     * 排序号
+     * 
+     * @return
+     */
+    public int getSortno() {
+        return sortno;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#getText()
+     */
+    @Override
+    public String getText() {
+        return text;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getValid() {
+        return valid;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#setCode(java.lang.String)
+     */
+    @Override
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#setId(java.lang.String)
+     */
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setLeaf(Boolean leaf) {
+        this.leaf = leaf;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#setPcode(java.lang.String)
+     */
+    @Override
+    public void setPcode(String pcode) {
+        this.pcode = pcode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#setPid(java.lang.String)
+     */
+    @Override
+    public void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    /**
+     * 排序号
+     * 
+     * @param sortno
+     */
+    public void setSortno(int sortno) {
+        this.sortno = sortno;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.web.code.entity.Code#setText(java.lang.String)
+     */
+    @Override
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public void setValid(Boolean valid) {
+        this.valid = valid;
+    }
+
+}

+ 65 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/code/service/impl/CodeServiceImpl.java

@@ -0,0 +1,65 @@
+package com.xtframe.sec.code.service.impl;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.util.Assert;
+
+import com.xtframe.core.code.entity.Code;
+import com.xtframe.core.code.service.CodeService;
+import com.xtframe.sec.code.dao.CodeDao;
+import com.xtframe.sec.code.entity.CodeEntity;
+import com.xtframe.sec.common.BaseSecurityService;
+
+public class CodeServiceImpl extends BaseSecurityService implements CodeService {
+    private CodeDao dao;
+
+    @Override
+    @Transactional
+    public String delete(String... ids) {
+        dao.delete(ids);
+        return null;
+    }
+
+    @Override
+    public Code findByCode(String code) {
+        return dao.findByCode(code);
+    }
+
+    @Override
+    public List<Code> findByPcode(String pcode) {
+        return dao.findByPcode(pcode);
+    }
+
+    /**
+     * 根据上级编码查询下级有效编码,并升序排序
+     */
+    @Override
+    public List<Code> findByPid(String pid) {
+        return dao.findByPidAndValidOrderBySortnoAsc(pid, true);
+    }
+
+    @Override
+    public Code findOne(String id) {
+        return dao.findOne(id);
+    }
+
+    @Override
+    public List<Code> findValidCodesByPid(String pid) {
+        return dao.findValidCodesByPid(pid);
+    }
+
+    @Override
+    public void init() {
+        this.dao = (CodeDao) getBeans().get("codeDao");
+        Assert.notNull(this.dao);
+    }
+
+    @Override
+    @Transactional
+    public Code save(Code code) {
+        if (code instanceof CodeEntity) { return dao.save((CodeEntity) code); }
+        return null;
+    }
+}

+ 21 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/BaseEntity.java

@@ -0,0 +1,21 @@
+package com.xtframe.sec.common;
+
+import java.io.Serializable;
+
+import org.springframework.data.repository.NoRepositoryBean;
+
+import com.xtframe.core.base.entity.Entity;
+
+/**
+ * Entity共通基类
+ * @author 袁晓冬
+ *
+ * @param <ID>
+ */
+@NoRepositoryBean
+public class BaseEntity<ID extends Serializable> extends Entity<ID> {
+
+    /** serialVersionUID */
+    private static final long serialVersionUID = -621459978272415856L;
+
+}

+ 43 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/BaseSecurityService.java

@@ -0,0 +1,43 @@
+package com.xtframe.sec.common;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.xtframe.core.base.service.BaseService;
+import com.xtframe.core.support.SecurityMgr;
+
+/**
+ * 安全服务基类接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public abstract class BaseSecurityService extends BaseService {
+    protected SecurityMgr securityMgr;
+    protected EntityManagerFactory entityManagerFactory;
+    protected EntityManager entityManager;
+
+    public EntityManager getEntityManager() {
+        return entityManager;
+    }
+
+    public EntityManagerFactory getEntityManagerFactory() {
+        return entityManagerFactory;
+    }
+
+    public SecurityMgr getSecurityMgr() {
+        return securityMgr;
+    }
+
+    public void setEntityManager(EntityManager entityManager) {
+        this.entityManager = entityManager;
+    }
+
+    public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
+        this.entityManagerFactory = entityManagerFactory;
+    }
+
+    public void setSecurityMgr(SecurityMgr securityMgr) {
+        this.securityMgr = securityMgr;
+    }
+}

+ 97 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/CaptchaFormAuthenticationFilter.java

@@ -0,0 +1,97 @@
+package com.xtframe.sec.common;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
+import org.apache.shiro.web.util.WebUtils;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.xtframe.core.base.ctl.WebJsonResult;
+import com.xtframe.core.org.entity.Org;
+import com.xtframe.core.support.SecurityMgr;
+import com.xtframe.core.support.aware.SecurityMgrAware;
+import com.xtframe.core.user.entity.User;
+import com.xtframe.core.utils.Assert;
+import com.xtframe.core.utils.CoreConstants;
+import com.xtframe.util.DateTime;
+
+/**
+ * 验证码表单认证
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter implements SecurityMgrAware {
+    private SecurityMgr securityMgr;
+
+    @Override
+    protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
+        return (request instanceof HttpServletRequest)
+                && WebUtils.toHttp(request).getMethod().equalsIgnoreCase(POST_METHOD);
+    }
+
+    @Override
+    protected boolean onLoginSuccess(AuthenticationToken token, org.apache.shiro.subject.Subject subject,
+            ServletRequest request, ServletResponse response) throws Exception {
+        Object principal = subject.getPrincipal();
+        Assert.isInstanceOf(User.class, principal);
+        User u = (User) principal;
+        Assert.notNull(u.getOrg(), "用户所在组织不能为空!");
+        Org org = securityMgr.orgService().findOne(u.getOrg());
+        Assert.notNull(org, "用户所在组织不能为空!");
+        subject.getSession().setAttribute(CoreConstants.SESSION_KEY_ORG, org);
+        return super.onLoginSuccess(token, subject, request, response);
+    }
+
+    @Override
+    public void setSecurityMgr(SecurityMgr securityMgr) {
+        this.securityMgr = securityMgr;
+    }
+
+    /**
+     * 判断是否为ajax请求
+     * 
+     * @param httpRequest
+     * @return
+     */
+    private boolean isAjaxRequest(HttpServletRequest httpRequest) {
+        Assert.notNull(httpRequest);
+        String acceptHeader = httpRequest.getHeader("accept");
+        if (acceptHeader != null && acceptHeader.indexOf("application/json") > -1) { return true; }
+        String xRequestedWith = httpRequest.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") > -1) { return true; }
+        return false;
+    }
+
+    /**
+     * 登录验证失败时不跳转,仅返回失败信息
+     */
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+        if (isLoginRequest(request, response)
+                || (request instanceof HttpServletRequest && !isAjaxRequest((HttpServletRequest) request))) {
+            return super.onAccessDenied(request, response);
+        }
+        else {
+            WebJsonResult res = new WebJsonResult();
+            res.setSuccess(false);
+            res.setMessage("_redirect_");
+            res.setAttr("url", getLoginUrl());
+            ObjectMapper mapper = new ObjectMapper();
+            mapper.setDateFormat(new SimpleDateFormat(DateTime.DATE_FORMAT_DATETIME));
+            try {
+                response.getWriter().write(mapper.writeValueAsString(res));
+            }
+            catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            return false;
+        }
+    }
+}

+ 15 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/MyOracleDialect.java

@@ -0,0 +1,15 @@
+package com.xtframe.sec.common;
+
+import java.sql.Types;
+
+import org.hibernate.dialect.Oracle10gDialect;
+import org.hibernate.type.StandardBasicTypes;
+
+public class MyOracleDialect extends Oracle10gDialect {
+    public MyOracleDialect() {
+        super();
+        registerHibernateType(-9, "string");
+
+        registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName());
+    }
+}

+ 22 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/OracleSqlConsts.java

@@ -0,0 +1,22 @@
+package com.xtframe.sec.common;
+
+/**
+ * Oracle检索语句定义
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface OracleSqlConsts {
+    /**
+     * 根据用户检索授权的功能
+     */
+    String queryFunctionByUser = "select f.* from T_XTFRAME_FUNC f join T_XTFRAME_USER_FUNC ufc on f.id=ufc.fid where ufc.userid=:userid";
+    /**
+     * 根据角色检索授权的功能
+     */
+    String queryFunctionByRole = "select f.* from T_XTFRAME_FUNC f join T_XTFRAME_ROLE_FUNC rfc on f.id=rfc.fid where rfc.rid=:roleid";
+    /**
+     * 根据组织检索授权的功能
+     */
+    String queryFunctionByOrg = "select f.* from T_XTFRAME_FUNC f join T_XTFRAME_ORG_FUNC ofc on f.id=ofc.fid where ofc.orgid=:orgid ";
+}

+ 90 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/QueryService.java

@@ -0,0 +1,90 @@
+package com.xtframe.sec.common;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Query;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
+
+/**
+ * 综合查询接口
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface QueryService {
+    /**
+     * 分页检索
+     * 
+     * @param spec
+     * @param pageable
+     * @param domainClass
+     * @return
+     */
+    public <T> Page<T> findAll(Specification<T> spec, Pageable pageable, Class<T> domainClass);
+
+    /**
+     * 根据条件检索
+     * 
+     * @param spec
+     * @param domainClass
+     * @return
+     */
+    public <T> List<T> findAll(Specification<T> spec, Class<T> domainClass);
+
+    /**
+     * 执行原生sql查询,与dao的同名方法一致
+     * 
+     * @param sqlString
+     * @param resultClass
+     * @param params
+     * @return
+     */
+    public <T> List<T> nativeQuery(String sqlString, Class<T> resultClass, Map<String, Object> params);
+
+    /**
+     * 执行原生sql查询,与dao的同名方法一致
+     * 
+     * @param sqlString
+     * @param params
+     * @return
+     */
+    public <T> List<?> nativeQuery(String sqlString, Map<String, Object> params);
+
+    /**
+     * Create an instance of <code>Query</code> for executing
+     * a native SQL statement, e.g., for update or delete.
+     * 
+     * @param sqlString
+     *            a native SQL query string
+     * @return the new query instance
+     */
+    public Query createNativeQuery(String sqlString);
+
+    /**
+     * Create an instance of <code>Query</code> for executing
+     * a native SQL query.
+     * 
+     * @param sqlString
+     *            a native SQL query string
+     * @param resultClass
+     *            the class of the resulting instance(s)
+     * @return the new query instance
+     */
+    public Query createNativeQuery(String sqlString, Class<?> resultClass);
+
+    /**
+     * Create an instance of <code>Query</code> for executing
+     * a native SQL query.
+     * 
+     * @param sqlString
+     *            a native SQL query string
+     * @param resultSetMapping
+     *            the name of the result set mapping
+     * @return the new query instance
+     */
+    public Query createNativeQuery(String sqlString, String resultSetMapping);
+}

+ 44 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepository.java

@@ -0,0 +1,44 @@
+package com.xtframe.sec.common;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.NoRepositoryBean;
+
+import com.xtframe.core.base.entity.Entity;
+
+/**
+ * Dao层共通基类<br>
+ * <p>
+ * 所有数据访问层(@Entity注解)继承此共通基类,实现数据访问层的共通处理。
+ * <p>
+ * 继承了{@link JpaRepository}接口,提供了大部分的数据CRUD处理,如果子类有特殊处理方法需要提供额外的接口
+ * <p>
+ * 在此处添加的接口方法所有Dao都可以使用,需要在MyCustomRepository实现方法
+ * 
+ * @param <E>
+ *            Dao所处理的Entity对象
+ * @param <PK>
+ *            Entity对象的主键类型,一般是{@link Long}
+ * @author 袁晓冬
+ */
+@NoRepositoryBean
+public interface SecRepository<T extends Entity<ID>, ID extends Serializable> extends JpaRepository<T, ID>,
+        JpaSpecificationExecutor<T> {
+
+    public List<T> nativeQuery(String sqlString, Class<T> resultClass, Map<String, Object> params);
+
+    public List<?> nativeQuery(String sqlString, Map<String, Object> params);
+
+    public int nativeUpdate(String sqlString, Map<String, Object> params);
+
+    /**
+     * 根据ID批量删除
+     * 
+     * @param ids
+     */
+    public void delete(ID[] ids);
+}

+ 64 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepositoryFactory.java

@@ -0,0 +1,64 @@
+package com.xtframe.sec.common;
+
+import static org.springframework.data.querydsl.QueryDslUtils.QUERY_DSL_PRESENT;
+
+import java.io.Serializable;
+
+import javax.persistence.EntityManager;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.support.JpaEntityInformation;
+import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
+import org.springframework.data.jpa.repository.support.QueryDslJpaRepository;
+import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
+import org.springframework.data.querydsl.QueryDslPredicateExecutor;
+import org.springframework.data.repository.core.RepositoryMetadata;
+
+public class SecRepositoryFactory extends JpaRepositoryFactory {
+
+    public SecRepositoryFactory(EntityManager entityManager) {
+        super(entityManager);
+    }
+
+    @Override
+    protected Object getTargetRepository(RepositoryMetadata metadata) {
+        return super.getTargetRepository(metadata);
+    }
+
+    /**
+     * Callback to create a {@link JpaRepository} instance with the given {@link EntityManager}
+     * 
+     * @param <T>
+     * @param <ID>
+     * @param entityManager
+     * @see #getTargetRepository(RepositoryMetadata)
+     * @return
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    protected <T, ID extends Serializable> SimpleJpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) {
+        Class<?> repositoryInterface = metadata.getRepositoryInterface();
+        JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
+
+        SimpleJpaRepository<?, ?> repo = isQueryDslExecutor(repositoryInterface) ? new QueryDslJpaRepository(entityInformation, entityManager)
+                : new SimpleSecRepository(entityInformation, entityManager);
+
+        return repo;
+    }
+
+    /**
+     * Returns whether the given repository interface requires a QueryDsl specific implementation to be chosen.
+     * 
+     * @param repositoryInterface
+     * @return
+     */
+    private boolean isQueryDslExecutor(Class<?> repositoryInterface) {
+
+        return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface);
+    }
+
+    @Override
+    protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
+        return SimpleSecRepository.class;
+    }
+}

+ 16 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SecRepositoryFactoryBean.java

@@ -0,0 +1,16 @@
+package com.xtframe.sec.common;
+
+import java.io.Serializable;
+
+import javax.persistence.EntityManager;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
+import org.springframework.data.repository.core.support.RepositoryFactorySupport;
+
+public class SecRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>> extends JpaRepositoryFactoryBean<T, Object, Serializable> {
+    @Override
+    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
+        return new SecRepositoryFactory(entityManager);
+    }
+}

+ 48 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SimplePageRequest.java

@@ -0,0 +1,48 @@
+package com.xtframe.sec.common;
+
+
+/**
+ * 分页参数对象
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class SimplePageRequest {
+    /** serialVersionUID */
+    int page;
+    int rows;
+    String sort = "id";
+    String order = "desc";
+
+    public String getOrder() {
+        return order;
+    }
+
+    public int getPage() {
+        return page;
+    }
+
+    public int getRows() {
+        return rows;
+    }
+
+    public String getSort() {
+        return sort;
+    }
+
+    public void setOrder(String order) {
+        this.order = order;
+    }
+
+    public void setPage(int page) {
+        this.page = page;
+    }
+
+    public void setRows(int rows) {
+        this.rows = rows;
+    }
+
+    public void setSort(String sort) {
+        this.sort = sort;
+    }
+}

+ 166 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SimpleSecRepository.java

@@ -0,0 +1,166 @@
+package com.xtframe.sec.common;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.jpa.repository.query.QueryUtils;
+import org.springframework.data.jpa.repository.support.JpaEntityInformation;
+import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
+import org.springframework.data.repository.NoRepositoryBean;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.xtframe.core.base.entity.Entity;
+import com.xtframe.core.utils.Assert;
+
+@NoRepositoryBean
+@SuppressWarnings("unchecked")
+public class SimpleSecRepository<T extends Entity<ID>, ID extends Serializable> extends SimpleJpaRepository<T, ID>
+        implements SecRepository<T, ID> {
+    protected final EntityManager entityManager;
+
+    public Page<T> findAll(Object condition, SimplePageRequest pageRequest) {
+        Sort newsort = new Sort(Direction.fromString(pageRequest.getOrder()), new String[] { pageRequest.getSort() });
+        // 页码从0开始
+        PageRequest pageable = new PageRequest(pageRequest.getPage() - 1, pageRequest.getRows(), newsort);
+        Assert.isInstanceOf(Specification.class, condition);
+        return findAll((Specification<T>) condition, pageable);
+    }
+
+    /**
+     * 重写查询时分页处理,如果当前页大于总页数,则返回最后一页,而不是空记录
+     */
+    @Override
+    public Page<T> findAll(Specification<T> spec, Pageable pageable) {
+        TypedQuery<T> query = null;
+        Method getCountQuery = null;
+        try {
+            Method queryMethod = SimpleJpaRepository.class.getDeclaredMethod("getQuery", Specification.class,
+                    Pageable.class);
+            getCountQuery = SimpleJpaRepository.class.getDeclaredMethod("getCountQuery", Specification.class);
+            queryMethod.setAccessible(true);
+            getCountQuery.setAccessible(true);
+            if (null != queryMethod) {
+                query = (TypedQuery<T>) queryMethod.invoke(this, spec, pageable);
+            }
+        }
+        catch (SecurityException e) {
+            e.printStackTrace();
+        }
+        catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+        catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        }
+        catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+        catch (InvocationTargetException e) {
+            e.printStackTrace();
+        }
+        if (pageable == null) { return new PageImpl<T>(query.getResultList()); }
+
+        query.setFirstResult(pageable.getOffset());
+        query.setMaxResults(pageable.getPageSize());
+        TypedQuery<Long> countQuery = null;
+        try {
+            countQuery = (TypedQuery<Long>) getCountQuery.invoke(this, spec);
+        }
+        catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        }
+        catch (IllegalAccessException e) {
+            e.printStackTrace();
+        }
+        catch (InvocationTargetException e) {
+            e.printStackTrace();
+        }
+        Long total = QueryUtils.executeCountQuery(countQuery);
+        List<T> content = null;
+        if (total > pageable.getOffset()) {
+            content = query.getResultList();
+        }
+        else {
+            if (total == 0) {
+                content = Collections.<T> emptyList();
+            }
+            else {
+                // 计算最后一页
+                long pages = total / pageable.getPageSize();
+                if (total % pageable.getPageSize() == 0) {
+                    pages -= 1;
+                }
+                query.setFirstResult((int) pages * pageable.getPageSize());
+                content = query.getResultList();
+            }
+        }
+        return new PageImpl<T>(content, pageable, total);
+    }
+
+    public SimpleSecRepository(Class<T> domainClass, EntityManager em) {
+        super(domainClass, em);
+        this.entityManager = em;
+    }
+
+    public SimpleSecRepository(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager) {
+        super(entityInformation, entityManager);
+        this.entityManager = entityManager;
+    }
+
+    @Override
+    public List<T> nativeQuery(String sqlString, Class<T> resultClass, Map<String, Object> params) {
+        Query query = entityManager.createNativeQuery(sqlString, resultClass);
+        if (null != params && params.size() > 0) {
+            for (Entry<String, Object> entry : params.entrySet()) {
+                query.setParameter(entry.getKey(), entry.getValue());
+            }
+        }
+        return query.getResultList();
+    }
+
+    @Override
+    public List<?> nativeQuery(String sqlString, Map<String, Object> params) {
+        Query query = entityManager.createNativeQuery(sqlString);
+        if (null != params && params.size() > 0) {
+            for (Entry<String, Object> entry : params.entrySet()) {
+                query.setParameter(entry.getKey(), entry.getValue());
+            }
+        }
+        return query.getResultList();
+    }
+
+    @Override
+    public int nativeUpdate(String sqlString, Map<String, Object> params) {
+        Query query = entityManager.createNativeQuery(sqlString);
+        if (null != params && params.size() > 0) {
+            for (Entry<String, Object> entry : params.entrySet()) {
+                query.setParameter(entry.getKey(), entry.getValue());
+            }
+        }
+        return query.executeUpdate();
+    }
+
+    @Override
+    @Transactional
+    public void delete(ID[] ids) {
+        for (ID id : ids) {
+            delete(id);
+        }
+    }
+}

+ 104 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SystemAuthenticationListener.java

@@ -0,0 +1,104 @@
+package com.xtframe.sec.common;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationListener;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.xtframe.core.user.entity.User;
+import com.xtframe.util.StringUtils;
+
+/**
+ * 用户登录监听<br>
+ * 记录所有登录凭证,提供用户登录查询
+ * 
+ * @author 袁晓冬
+ */
+@Component
+public class SystemAuthenticationListener implements AuthenticationListener {
+    /** log */
+    private static final Logger LOG = LoggerFactory.getLogger(SystemAuthenticationListener.class);
+    /** 登录凭证与session Map */
+    private Map<PrincipalCollection, Session> authSubjectMap = new HashMap<PrincipalCollection, Session>();
+    /** session超时属性判断 */
+    private static final String SESSION_FLG = "session_outTime_flg";
+
+    @Override
+    public void onSuccess(AuthenticationToken token, AuthenticationInfo info) {
+        Session session = SecurityUtils.getSubject().getSession();
+        session.setAttribute(SESSION_FLG, "");
+        authSubjectMap.put(info.getPrincipals(), session);
+        LOG.debug("use login:" + token.getPrincipal());
+        cleanCache();
+    }
+
+    @Override
+    public void onFailure(AuthenticationToken token, AuthenticationException ae) {
+    }
+
+    @Override
+    public void onLogout(PrincipalCollection principals) {
+        PrincipalCollection principal = SecurityUtils.getSubject().getPrincipals();
+        if (authSubjectMap.containsKey(principal)) {
+            authSubjectMap.remove(principal);
+            LOG.debug("use logout:" + principal);
+        }
+    }
+
+    /**
+     * 清理session缓存,删除已超时的无效session
+     */
+    private void cleanCache() {
+        Iterator<Entry<PrincipalCollection, Session>> it = authSubjectMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Entry<PrincipalCollection, Session> entry = it.next();
+            Session sessionOld = entry.getValue();
+            try {
+                // 超时的session此行会抛出IllegalStateException异常
+                Object flg = sessionOld.getAttribute(SESSION_FLG);
+                if (null == flg) {
+                    it.remove();
+                    LOG.debug("use timeout:" + entry.getKey());
+                }
+            } catch (InvalidSessionException e) {
+                it.remove();
+                LOG.debug("use timeout:" + entry.getKey());
+            } catch (IllegalStateException e) {
+                it.remove();
+                LOG.debug("use timeout:" + entry.getKey());
+            }
+        }
+    }
+
+    /**
+     * 用户是否登录判断
+     */
+    public boolean isLogin(String userLoginName) {
+        if (!StringUtils.hasLength(userLoginName)) {
+            return false;
+        }
+        cleanCache();
+        // 遍历缓存的PrincipalCollection,查找匹配的用户登录名称
+        for (Entry<PrincipalCollection, Session> entry : authSubjectMap.entrySet()) {
+            Object principal = entry.getKey().getPrimaryPrincipal();
+            if (principal instanceof User) {
+                User user = (User) principal;
+                return null != user && userLoginName.equals(user.getUname());
+            }
+        }
+        return false;
+    }
+
+}

+ 91 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/common/SystemParamEntity.java

@@ -0,0 +1,91 @@
+package com.xtframe.sec.common;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xtframe.sec.utils.BooleanSerializer;
+
+/**
+ * 系统参数实体
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Entity
+@Table(name = "t_xtframe_sys_param")
+public class SystemParamEntity extends BaseEntity<String> {
+    /** serialVersionUID */
+    private static final long serialVersionUID = -5486007282182900974L;
+    /** UUID主键 */
+    protected String id;
+    /** 参数主键 */
+    protected String key;
+    /** 参数值 */
+    protected String value;
+    /** 是否有效 */
+    @JsonSerialize(using = BooleanSerializer.class)
+    protected Boolean valid;
+    /** 参数所属类 */
+    protected String clazz;
+    /** 描述 */
+    protected String disp;
+
+    public String getClazz() {
+        return clazz;
+    }
+
+    public String getDisp() {
+        return disp;
+    }
+
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getValid() {
+        return valid;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setClazz(String clazz) {
+        this.clazz = clazz;
+    }
+
+    public void setDisp(String disp) {
+        this.disp = disp;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public void setValid(Boolean valid) {
+        this.valid = valid;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}

+ 50 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/dao/DataPermDao.java

@@ -0,0 +1,50 @@
+package com.xtframe.sec.data.dao;
+
+import java.util.List;
+
+import com.xtframe.core.data.entity.DataPerm;
+import com.xtframe.sec.common.SecRepository;
+import com.xtframe.sec.data.entity.DataPermEntity;
+
+/**
+ * 数据处理接口
+ * 
+ * @author 袁晓冬
+ */
+public interface DataPermDao extends SecRepository<DataPermEntity, String> {
+    /**
+     * 根据业务主键和用户ID查询权限
+     * 
+     * @param busskey
+     * @param user
+     * @return
+     */
+    public List<DataPerm> findByBusskeyAndUserId(String busskey, String userId);
+
+    /**
+     * 根据业务主键查询权限
+     * 
+     * @param busskey
+     * @return
+     */
+    public List<DataPerm> findByBusskey(String busskey);
+
+    /**
+     * 根据业务主键和数据类型查询权限
+     * 
+     * @param busskey
+     * @param dataType
+     * @return
+     */
+    public List<DataPerm> findByBusskeyAndDataType(String busskey, String dataType);
+
+    /**
+     * 根据业务主键和角色编码查询
+     * 
+     * @param busskey
+     * @param role
+     * @return
+     */
+    public List<DataPerm> findByBusskeyAndRoleCode(String busskey, String roleCode);
+
+}

+ 153 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/entity/DataPermEntity.java

@@ -0,0 +1,153 @@
+package com.xtframe.sec.data.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import com.xtframe.core.data.entity.DataPerm;
+import com.xtframe.sec.common.BaseEntity;
+
+/**
+ * 数据权限实体
+ * 
+ * @author 袁晓冬
+ *
+ */
+@Entity
+@Table(name = "t_xtframe_data_perm")
+public class DataPermEntity extends BaseEntity<String> implements DataPerm {
+    /** serialVersionUID */
+    private static final long serialVersionUID = 8277353534304142863L;
+    private String id, busskey, userId, roleCode, dataType, oper;
+    private String text1,text2,text3,text4,text5;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#getBusskey()
+     */
+    @Override
+    public String getBusskey() {
+        return busskey;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#getDataType()
+     */
+    @Override
+    public String getDataType() {
+        return dataType;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#getId()
+     */
+    @Override
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    public String getOper() {
+        return oper;
+    }
+
+    public String getRoleCode() {
+        return roleCode;
+    }
+
+    public String getText1() {
+        return text1;
+    }
+
+    public String getText2() {
+        return text2;
+    }
+
+    public String getText3() {
+        return text3;
+    }
+
+    public String getText4() {
+        return text4;
+    }
+
+    public String getText5() {
+        return text5;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#setBusskey(java.lang.String)
+     */
+    @Override
+    public void setBusskey(String busskey) {
+        this.busskey = busskey;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#setDataType(java.lang.String)
+     */
+    @Override
+    public void setDataType(String dataType) {
+        this.dataType = dataType;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.xtframe.sec.data.entity.DataPerm#setId(java.lang.String)
+     */
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setOper(String oper) {
+        this.oper = oper;
+    }
+
+    public void setRoleCode(String roleCode) {
+        this.roleCode = roleCode;
+    }
+
+    public void setText1(String text1) {
+        this.text1 = text1;
+    }
+
+    public void setText2(String text2) {
+        this.text2 = text2;
+    }
+
+    public void setText3(String text3) {
+        this.text3 = text3;
+    }
+
+    public void setText4(String text4) {
+        this.text4 = text4;
+    }
+
+    public void setText5(String text5) {
+        this.text5 = text5;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+}

+ 85 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/data/service/impl/DataPermServiceImpl.java

@@ -0,0 +1,85 @@
+package com.xtframe.sec.data.service.impl;
+
+import java.util.List;
+
+import com.xtframe.core.data.entity.DataPerm;
+import com.xtframe.core.data.service.DataPermService;
+import com.xtframe.core.utils.Assert;
+import com.xtframe.sec.common.BaseSecurityService;
+import com.xtframe.sec.data.dao.DataPermDao;
+import com.xtframe.sec.data.entity.DataPermEntity;
+import com.xtframe.util.StringUtils;
+
+/**
+ * 数据权限服务实现
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class DataPermServiceImpl extends BaseSecurityService implements DataPermService {
+    private DataPermDao dao;
+
+    @Override
+    public String checkRolePermission(String busskey, String roleCode) {
+        List<DataPerm> perms = dao.findByBusskeyAndRoleCode(busskey, roleCode);
+        return toPerms(perms);
+    }
+
+    @Override
+    public String checkUserPermission(String busskey, String userId) {
+        List<DataPerm> perms = dao.findByBusskeyAndUserId(busskey, userId);
+        return toPerms(perms);
+    }
+
+    @Override
+    public String delete(String... ids) {
+        dao.delete(ids);
+        return null;
+    }
+
+    @Override
+    public List<DataPerm> findByBusskey(String busskey) {
+        return dao.findByBusskey(busskey);
+    }
+
+    @Override
+    public List<DataPerm> findByBusskeyAndDataType(String busskey, String dataType) {
+        return dao.findByBusskeyAndDataType(busskey, dataType);
+    }
+
+    @Override
+    public List<DataPerm> findByBusskeyAndUserId(String busskey, String userId) {
+        return dao.findByBusskeyAndUserId(busskey, userId);
+    }
+
+    @Override
+    public DataPerm findOne(String id) {
+        return dao.findOne(id);
+    }
+
+    @Override
+    public void init() {
+        this.dao = (DataPermDao) getBeans().get("dataPermDao");
+        Assert.notNull(this.dao);
+    }
+
+    @Override
+    public DataPerm save(DataPerm dp) {
+        Assert.isInstanceOf(DataPermEntity.class, dp);
+        return dao.save((DataPermEntity) dp);
+    }
+
+    private String toPerms(List<DataPerm> perms) {
+        if (perms.size() == 0) { return null; }
+        StringBuilder permBuilder = new StringBuilder("");
+        for (DataPerm dp : perms) {
+            permBuilder.append(dp.getOper());
+            permBuilder.append(";");
+        }
+        if (permBuilder.length() > 0) {
+            permBuilder.deleteCharAt(permBuilder.length() - 1);
+        }
+        return permBuilder.toString();
+    }
+
+}

+ 14 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/dao/JobInfoDao.java

@@ -0,0 +1,14 @@
+package com.xtframe.sec.job.dao;
+
+import com.xtframe.sec.common.SecRepository;
+import com.xtframe.sec.job.entity.JobInfoEntity;
+
+/**
+ * 定时任务Dao
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface JobInfoDao extends SecRepository<JobInfoEntity, String> {
+
+}

+ 174 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/entity/JobInfoEntity.java

@@ -0,0 +1,174 @@
+package com.xtframe.sec.job.entity;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xtframe.core.job.entity.JobInfo;
+import com.xtframe.sec.common.BaseEntity;
+import com.xtframe.sec.utils.BooleanSerializer;
+
+@Entity
+@Table(name = "t_xtframe_jobinfo")
+public class JobInfoEntity extends BaseEntity<String> implements JobInfo {
+    /** serialVersionUID */
+    private static final long serialVersionUID = -1237921381858233178L;
+    /** 任务标识前缀 */
+    public static final String JOB_PREFIX = "job_";
+    /** 任务分组前缀 */
+    public static final String GROUP_PREFIX = "group_";
+    /** 任务主键 */
+    private String id;
+    /** 任务描述 */
+    private String disp;
+    /** 任务创建时间 */
+    private Date createTime;
+    /** 任务启动时间,正式开始运行任务的时间 */
+    private Date startTime;
+    /** 任务结束时间 */
+    private Date endTime;
+    /** 是否循环 */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean circle;
+    /** 执行接口 */
+    private String clazz;
+    /** 时间表达式 */
+    private String cronExpression;
+    /** 上次执行结果 */
+    private String result;
+    /** 间隔时间 */
+    private int interval;
+    /** 任务状态 */
+    private String status;
+    /** 执行参数 */
+    private String param;
+
+    @Type(type = "yes_no")
+    public Boolean getCircle() {
+        return circle;
+    }
+
+    public String getClazz() {
+        return clazz;
+    }
+
+    @Override
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public String getCronExpression() {
+        return cronExpression;
+    }
+
+    @Override
+    public String getDisp() {
+        return disp;
+    }
+
+    @Override
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    @Override
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public int getInterval() {
+        return interval;
+    }
+
+    @Override
+    @Transient
+    public String getJobGroup() {
+        return JOB_PREFIX + id;
+    }
+
+    @Override
+    @Transient
+    public String getJobName() {
+        return GROUP_PREFIX + id;
+    }
+
+    @Override
+    public String getParam() {
+        return param;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    @Override
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    @Override
+    public String getStatus() {
+        return status;
+    }
+
+    public void setCircle(Boolean circle) {
+        this.circle = circle;
+    }
+
+    public void setClazz(String clazz) {
+        this.clazz = clazz;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public void setCronExpression(String cronExpression) {
+        this.cronExpression = cronExpression;
+    }
+
+    public void setDisp(String disp) {
+        this.disp = disp;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setInterval(int interval) {
+        this.interval = interval;
+    }
+
+    public void setParam(String param) {
+        this.param = param;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+}

+ 82 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/impl/CommonJobListener.java

@@ -0,0 +1,82 @@
+package com.xtframe.sec.job.impl;
+
+import java.util.Date;
+
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.JobListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.xtframe.core.job.entity.JobInfo;
+import com.xtframe.core.job.service.JobInfoService;
+import com.xtframe.core.support.SecurityMgr;
+import com.xtframe.sec.log.dao.BizLogDao;
+import com.xtframe.sec.log.entity.BizLogEntity;
+
+public class CommonJobListener implements JobListener {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+    private SecurityMgr mgr = null;
+    private BizLogDao logDao;
+
+    public BizLogDao getLogDao() {
+        return logDao;
+    }
+
+    public void setLogDao(BizLogDao logDao) {
+        this.logDao = logDao;
+    }
+
+    public void setMgr(SecurityMgr mgr) {
+        this.mgr = mgr;
+    }
+
+    @Override
+    public String getName() {
+        return CommonJobListener.class.getSimpleName();
+    }
+
+    private JobInfo getJobInfoFromContext(JobExecutionContext context) {
+        return (JobInfo) context.getJobDetail().getJobDataMap().get(JobInfoService.PARAM_JOB);
+    }
+
+    @Override
+    public void jobToBeExecuted(JobExecutionContext context) {
+        JobInfo info = getJobInfoFromContext(context);
+        info.setStartTime(new Date());
+        mgr.jobService().save(info);
+        BizLogEntity logEntity = new BizLogEntity();
+        logEntity.setMethod("com.xtframe.sec.job.impl.CommonJobListener.jobToBeExecuted");
+        logEntity.setInsertTime(new Date());
+        logEntity.setOs("sys");
+        logEntity.setRemark("start job ID:" + info.getId());
+        logDao.save(logEntity);
+        logger.debug("jobToBeExecuted:{}", info.getJobName());
+    }
+
+    @Override
+    public void jobExecutionVetoed(JobExecutionContext context) {
+        JobInfo info = getJobInfoFromContext(context);
+        BizLogEntity logEntity = new BizLogEntity();
+        logEntity.setMethod("com.xtframe.sec.job.impl.CommonJobListener.jobExecutionVetoed");
+        logEntity.setInsertTime(new Date());
+        logEntity.setOs("sys");
+        logEntity.setRemark("vetoed job ID:" + info.getId());
+        logDao.save(logEntity);
+        logger.debug("jobExecutionVetoed:{}", info.getJobName());
+    }
+
+    @Override
+    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
+        JobInfo info = getJobInfoFromContext(context);
+        info.setEndTime(new Date());
+        mgr.jobService().save(info);
+        BizLogEntity logEntity = new BizLogEntity();
+        logEntity.setMethod("com.xtframe.sec.job.impl.CommonJobListener.jobWasExecuted");
+        logEntity.setInsertTime(new Date());
+        logEntity.setOs("sys");
+        logEntity.setRemark("executed job ID:" + info.getId());
+        logDao.save(logEntity);
+        logger.debug("jobWasExecuted:{}", info.getJobName());
+    }
+}

+ 258 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/job/impl/JobInfoServiceImpl.java

@@ -0,0 +1,258 @@
+package com.xtframe.sec.job.impl;
+
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.JobListener;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerBuilder;
+import org.quartz.TriggerKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.Assert;
+
+import com.xtframe.core.job.entity.JobInfo;
+import com.xtframe.core.job.service.JobInfoService;
+import com.xtframe.sec.common.BaseSecurityService;
+import com.xtframe.sec.job.dao.JobInfoDao;
+import com.xtframe.sec.job.entity.JobInfoEntity;
+import com.xtframe.sec.log.dao.BizLogDao;
+import com.xtframe.util.StringUtils;
+
+/**
+ * 定时任务服务
+ * 
+ * @author 袁晓冬
+ *
+ */
+public class JobInfoServiceImpl extends BaseSecurityService implements JobInfoService {
+    private static final Logger LOG = LoggerFactory.getLogger(JobInfoServiceImpl.class);
+    private JobInfoDao dao;
+    private Scheduler scheduler = null;
+    private JobListener listener = new CommonJobListener();
+    private BizLogDao logDao;
+
+    @Override
+    public int addJob(JobInfo jobInfo) {
+        // 任务名称和任务组设置规则:
+        // 名称:task_1 ..
+        // 组 :group_1 ..
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        CronTrigger trigger = null;
+        try {
+            trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+        // 不存在,创建一个
+        if (null == trigger) {
+            Class<?> c = null;
+            try {
+                c = Class.forName(jobInfo.getClazz());
+            }
+            catch (Exception e) {
+                LOG.error("定时任务加载类找不到:" + jobInfo.getClazz());
+                return -1;
+            }
+            LOG.error("加载定时任务:" + jobInfo.getClazz());
+            // quartz job
+            if (org.quartz.Job.class.isAssignableFrom(c)) {
+                try {
+                    addQuartzJob(jobInfo);
+                }
+                catch (ClassNotFoundException | SchedulerException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        else {
+            // 按新的trigger重新设置job执行
+            try {
+                scheduler.rescheduleJob(triggerKey, getTriggerFromJobInfo(jobInfo));
+            }
+            catch (SchedulerException e) {
+                e.printStackTrace();
+            }
+        }
+        return 0;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void addQuartzJob(JobInfo jobInfo) throws ClassNotFoundException, SchedulerException {
+        Class<?> c = Class.forName(jobInfo.getClazz());
+        if (!org.quartz.Job.class.isAssignableFrom(c)) { return; }
+        JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) c)
+                .withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup()).build();
+        jobDetail.getJobDataMap().put(PARAM_JOB, jobInfo);
+        // 按新的表达式构建一个新的trigger
+        scheduler.scheduleJob(jobDetail, getTriggerFromJobInfo(jobInfo));
+    }
+
+    @Override
+    public String delete(String... ids) {
+        dao.delete(ids);
+        return null;
+    }
+
+    @Override
+    public int deleteJob(JobInfo jobInfo) {
+        JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        try {
+            scheduler.deleteJob(jobKey);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+            return -1;
+        }
+        return 0;
+    }
+
+    @Override
+    public JobInfo findOne(String id) {
+        return dao.findOne(id);
+    }
+
+    public JobListener getListener() {
+        return listener;
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private Trigger getTriggerFromJobInfo(JobInfo jobInfo) {
+        // 按新的表达式构建一个新的trigger
+        TriggerBuilder tb = TriggerBuilder.newTrigger().withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup());
+        if (StringUtils.isEmpty(jobInfo.getCronExpression())) {
+            tb.startAt(jobInfo.getStartTime());
+            if (jobInfo.getCircle()) {
+                // 换算成秒
+                tb.withSchedule(simpleSchedule().withIntervalInSeconds(jobInfo.getInterval()).repeatForever());
+            }
+        }
+        else {
+            tb.withSchedule(cronSchedule(jobInfo.getCronExpression()));
+        }
+        return tb.build();
+    }
+
+    @Override
+    public void init() {
+        this.dao = (JobInfoDao) getBeans().get("jobInfoDao");
+        this.logDao = (BizLogDao) getBeans().get("bizLogDao");
+        Assert.notNull(this.dao);
+    }
+
+    @Override
+    public void initJobs(Object param) {
+        if (param instanceof Scheduler) {
+            if (listener instanceof CommonJobListener) {
+                ((CommonJobListener) listener).setLogDao(logDao);
+                ((CommonJobListener) listener).setMgr(securityMgr);
+            }
+            scheduler = (Scheduler) param;
+            try {
+                scheduler.getListenerManager().addJobListener(listener);
+            }
+            catch (SchedulerException e) {
+                e.printStackTrace();
+            }
+        }
+        else {
+            return;
+        }
+        Scheduler scheduler = (Scheduler) param;
+        // 可执行的任务列表
+        List<JobInfo> jobs = queryAllJob();
+        for (JobInfo job : jobs) {
+            addJob(job);
+        }
+        try {
+            scheduler.start();
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public int pauseJob(JobInfo jobInfo) {
+        JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        try {
+            scheduler.pauseJob(jobKey);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+            return -1;
+        }
+        return 0;
+    }
+
+    @Override
+    public List<JobInfo> queryAllJob() {
+        List<JobInfo> jobs = new ArrayList<JobInfo>();
+        for (JobInfoEntity j : dao.findAll()) {
+            jobs.add(j);
+        }
+        return jobs;
+    }
+
+    @Override
+    public int resumeJob(JobInfo jobInfo) {
+        JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        try {
+            scheduler.resumeJob(jobKey);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+            return -1;
+        }
+        return 0;
+    }
+
+    @Override
+    public JobInfo save(JobInfo jobInfo) {
+        if (jobInfo instanceof JobInfoEntity) { return dao.save((JobInfoEntity) jobInfo); }
+        return null;
+    }
+
+    public void setListener(JobListener listener) {
+        this.listener = listener;
+    }
+
+    @Override
+    public int triggerJob(JobInfo jobInfo) {
+        JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        try {
+            scheduler.triggerJob(jobKey);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+            return -1;
+        }
+        return 0;
+    }
+
+    @Override
+    public int updateJob(JobInfo jobInfo) {
+        Trigger trigger = getTriggerFromJobInfo(jobInfo);
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
+        //按新的trigger重新设置job执行
+        try {
+            scheduler.rescheduleJob(triggerKey, trigger);
+        }
+        catch (SchedulerException e) {
+            e.printStackTrace();
+            return -1;
+        }
+        return 0;
+    }
+}

+ 13 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/dao/BizLogDao.java

@@ -0,0 +1,13 @@
+package com.xtframe.sec.log.dao;
+
+import com.xtframe.sec.common.SecRepository;
+import com.xtframe.sec.log.entity.BizLogEntity;
+
+/**
+ * 业务日志记录Dao
+ * 
+ * @author 袁晓冬
+ *
+ */
+public interface BizLogDao extends SecRepository<BizLogEntity, String> {
+}

+ 275 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/entity/BizLogEntity.java

@@ -0,0 +1,275 @@
+package com.xtframe.sec.log.entity;
+
+import java.util.Date;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import com.xtframe.core.anon.BizLog.LogType;
+import com.xtframe.sec.common.BaseEntity;
+import com.xtframe.util.StringUtils;
+
+@Entity
+@Table(name = "T_XTFRAME_BIZ_LOG")
+public class BizLogEntity extends BaseEntity<String> {
+    /** serialVersionUID */
+    private static final long serialVersionUID = 2988511622248982196L;
+    /** UUID主键 */
+    private String id;
+    /** 操作人ID */
+    private String userid;
+    /** 操作类型 */
+    private String logType;
+    /** 访问类型 */
+    private String handlerType;
+    /** 客户端IP */
+    private String ip;
+    /** 操作耗时 */
+    private long cost;
+    /** 方法名 */
+    private String method;
+    /** 请求参数 */
+    private String param;
+    /** 请求URL */
+    private String url;
+    /** 浏览器 */
+    private String browser;
+    /** 操作系统 */
+    private String os;
+    /** 备注 */
+    private String remark;
+    /** 创建时间 */
+    private Date insertTime = new Date();
+
+    /**
+     * 浏览器
+     * 
+     * @return
+     */
+    public String getBrowser() {
+        return browser;
+    }
+
+    /**
+     * 操作耗时
+     * 
+     * @return
+     */
+    public long getCost() {
+        return cost;
+    }
+
+    /**
+     * 访问类型<br>
+     * pre,post,afterCompletion
+     * 
+     * @return
+     */
+    public String getHandlerType() {
+        return handlerType;
+    }
+
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * 日志插入时间
+     * 
+     * @return
+     */
+    public Date getInsertTime() {
+        return insertTime;
+    }
+
+    /**
+     * 客户端IP
+     * 
+     * @return
+     */
+    public String getIp() {
+        return ip;
+    }
+
+    /**
+     * 操作类型<br>
+     * {@link LogType}
+     * 
+     * @return
+     */
+    public String getLogType() {
+        return logType;
+    }
+
+    /**
+     * 方法名
+     * 
+     * @return
+     */
+    public String getMethod() {
+        return method;
+    }
+
+    public String getOs() {
+        return os;
+    }
+
+    /**
+     * 请求参数
+     * 
+     * @return
+     */
+    public String getParam() {
+        return param;
+    }
+
+    /**
+     * 备注
+     * 
+     * @return
+     */
+    public String getRemark() {
+        return remark;
+    }
+
+    /**
+     * 请求URL
+     * 
+     * @return
+     */
+    public String getUrl() {
+        return url;
+    }
+
+    /**
+     * 操作人ID
+     * 
+     * @return
+     */
+    public String getUserid() {
+        return userid;
+    }
+
+    /**
+     * 浏览器
+     * 
+     * @param browser
+     */
+    public void setBrowser(String browser) {
+        this.browser = browser;
+    }
+
+    /**
+     * 操作耗时
+     * 
+     * @param cost
+     */
+    public void setCost(long cost) {
+        this.cost = cost;
+    }
+
+    /**
+     * 访问类型<br>
+     * pre,post,afterCompletion
+     * 
+     * @param handlerType
+     */
+    public void setHandlerType(String handlerType) {
+        this.handlerType = handlerType;
+    }
+
+    /**
+     * UUID主键,系统自动生成
+     * 
+     * @param id
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * 日志插入时间
+     * 
+     * @param insertTime
+     */
+    public void setInsertTime(Date insertTime) {
+        this.insertTime = insertTime;
+    }
+
+    /**
+     * 客户端IP
+     * 
+     * @param ip
+     */
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
+
+    /**
+     * 操作类型<br>
+     * {@link LogType}
+     * 
+     * @param logType
+     */
+
+    public void setLogType(String logType) {
+        this.logType = logType;
+    }
+
+    /**
+     * 方法名
+     * 
+     * @param method
+     */
+    public void setMethod(String method) {
+        this.method = StringUtils.toLimitLength(method, 250);
+    }
+
+    public void setOs(String os) {
+        this.os = os;
+    }
+
+    /**
+     * 请求参数
+     * 
+     * @param param
+     */
+    public void setParam(String param) {
+        this.param = param;
+    }
+
+    /**
+     * 备注
+     * 
+     * @param remark
+     */
+    public void setRemark(String remark) {
+        remark = remark.replaceAll("\\s*|\t|\r|\n", "");
+        this.remark = StringUtils.toLimitLength(remark, 250);
+    }
+
+    /**
+     * 设置请求URL
+     * 
+     * @param url
+     */
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /**
+     * 操作人ID
+     * 
+     * @param userid
+     */
+    public void setUserid(String userid) {
+        this.userid = userid;
+    }
+}

+ 301 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/log/service/impl/SpringMvcBizLogRecorder.java

@@ -0,0 +1,301 @@
+package com.xtframe.sec.log.service.impl;
+
+import java.util.Enumeration;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.transaction.Transactional;
+
+import org.springframework.web.HttpRequestHandler;
+import org.springframework.web.method.HandlerMethod;
+
+import com.xtframe.core.anon.BizLog;
+import com.xtframe.core.log.BizLogRecorder;
+import com.xtframe.core.support.SecurityMgr;
+import com.xtframe.core.support.aware.SecurityMgrAware;
+import com.xtframe.core.user.entity.User;
+import com.xtframe.sec.common.BaseSecurityService;
+import com.xtframe.sec.log.dao.BizLogDao;
+import com.xtframe.sec.log.entity.BizLogEntity;
+import com.xtframe.util.Exceptions;
+import com.xtframe.util.StringUtils;
+
+public class SpringMvcBizLogRecorder extends BaseSecurityService implements BizLogRecorder, SecurityMgrAware {
+    private SecurityMgr securityMgr;
+    private BizLogDao dao;
+
+    @Override
+    public void init() {
+        this.dao = (BizLogDao) beans.get("bizLogDao");
+        super.init();
+    }
+
+    @Override
+    public void log(Object request, Object response, Object handler, HandlerType type, long cost) {
+        User u = securityMgr.getCurrUser();
+        if (u == null) { return; }
+        if (handler instanceof HttpRequestHandler) { return; }
+        BizLogEntity entity = null;
+        switch (type) {
+        case PreHandle:
+            entity = logPreHandle(request, response, handler);
+            break;
+        case PostHandle:
+            entity = logPostHandle(request, response, handler, cost);
+            break;
+        case AfterCompletion:
+            entity = logAfterCompletion(request, response, handler, cost);
+            break;
+        case Exception:
+            entity = logException(request, response, handler, cost);
+            break;
+        default:
+            break;
+        }
+        entity.setHandlerType(type.getValue());
+        save(entity);
+    }
+
+    /**
+     * 处理器日志记录
+     * 
+     * @param handler
+     */
+    private BizLogEntity logPreHandle(Object request, Object response, Object handler) {
+        BizLogEntity entity = new BizLogEntity();
+        entity.setUserid(securityMgr.getCurrUser().getId());
+        if (handler instanceof HandlerMethod) {
+            writeHandlerMethodToBizLog(entity, (HandlerMethod) handler);
+        }
+        if (request instanceof HttpServletRequest) {
+            writeRequestToBizLog(entity, (HttpServletRequest) request);
+        }
+        return entity;
+    }
+
+    /**
+     * 处理后日志记录
+     * 
+     * @param handler
+     * @param cost
+     */
+    private BizLogEntity logPostHandle(Object request, Object response, Object handler, long cost) {
+        BizLogEntity entity = new BizLogEntity();
+        entity.setUserid(securityMgr.getCurrUser().getId());
+        entity.setCost(cost);
+        if (handler instanceof HandlerMethod) {
+            writeHandlerMethodToBizLog(entity, (HandlerMethod) handler);
+        }
+        if (request instanceof HttpServletRequest) {
+            writeRequestToBizLog(entity, (HttpServletRequest) request);
+        }
+        return entity;
+    }
+
+    /**
+     * 渲染后日志记录
+     * 
+     * @param handler
+     * @param cost
+     */
+    private BizLogEntity logAfterCompletion(Object request, Object response, Object handler, long cost) {
+        BizLogEntity entity = new BizLogEntity();
+        entity.setUserid(securityMgr.getCurrUser().getId());
+        entity.setCost(cost);
+        if (handler instanceof HandlerMethod) {
+            writeHandlerMethodToBizLog(entity, (HandlerMethod) handler);
+        }
+        if (request instanceof HttpServletRequest) {
+            writeRequestToBizLog(entity, (HttpServletRequest) request);
+        }
+        return entity;
+    }
+
+    /**
+     * 记录异常
+     * 
+     * @param request
+     * @param response
+     * @param handler
+     * @param cost
+     * @return
+     */
+    private BizLogEntity logException(Object request, Object response, Object handler, long cost) {
+        BizLogEntity entity = new BizLogEntity();
+        entity.setUserid(securityMgr.getCurrUser().getId());
+        entity.setCost(cost);
+        if (handler instanceof HandlerMethod) {
+            writeHandlerMethodToBizLog(entity, (HandlerMethod) handler);
+        }
+        if (request instanceof HttpServletRequest) {
+            writeRequestToBizLog(entity, (HttpServletRequest) request);
+        }
+        if (response instanceof Exception) {
+            Exception ex = (Exception) response;
+            entity.setRemark(StringUtils.toLimitLength(Exceptions.getStackTraceAsString(ex), 250));
+        }
+        return entity;
+    }
+
+    /**
+     * 获取HandlerMethod日志信息
+     * 
+     * @param entity
+     * @param method
+     */
+    private void writeHandlerMethodToBizLog(BizLogEntity entity, HandlerMethod method) {
+        entity.setMethod(method.getMethod().toString());
+        BizLog log = method.getMethod().getAnnotation(BizLog.class);
+        if (null != log) {
+            entity.setLogType(log.value().toString());
+        }
+    }
+
+    /**
+     * 获取HttpServletRequest日志信息
+     * 
+     * @param entity
+     * @param request
+     */
+    @SuppressWarnings("unchecked")
+    private void writeRequestToBizLog(BizLogEntity entity, HttpServletRequest request) {
+        entity.setUrl(request.getRequestURL().toString());
+        String userAgent = request.getHeader("user-agent");
+        entity.setOs(getClientOS(userAgent));
+        entity.setBrowser(getBrowser(userAgent));
+        entity.setIp(request.getRemoteAddr());
+        Enumeration<String> em = request.getParameterNames();
+        StringBuilder params = new StringBuilder();
+        while (em.hasMoreElements()) {
+            String name = em.nextElement();
+            String value = request.getParameter(name);
+            params.append(name);
+            params.append("=");
+            params.append(value);
+            params.append(";");
+        }
+        if (params.length() > 250) {
+            params.setLength(250);
+        }
+        entity.setParam(params.toString());
+    }
+
+    @Transactional
+    private void save(BizLogEntity entity) {
+        dao.save(entity);
+    }
+
+    @Override
+    public void setSecurityMgr(SecurityMgr securityMgr) {
+        this.securityMgr = securityMgr;
+    }
+
+    /**
+     * 获取客户端操作系统信息,目前只匹配Win 7、WinXP、Win2003、Win2000、MAC、WinNT、Linux、Mac68k、Win9x
+     * 
+     * @param userAgent
+     *            request.getHeader("user-agent")的返回值
+     * @return
+     */
+    private String getClientOS(String userAgent) {
+        String cos = "unknow os";
+
+        Pattern p = Pattern.compile(".*(Windows NT 6\\.1).*");
+        Matcher m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Win 7";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(Windows NT 5\\.1|Windows XP).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "WinXP";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(Windows NT 5\\.2).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Win2003";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(Win2000|Windows 2000|Windows NT 5\\.0).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Win2000";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(Mac|apple|MacOS8).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "MAC";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(WinNT|Windows NT).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "WinNT";
+            return cos;
+        }
+
+        p = Pattern.compile(".*Linux.*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Linux";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(68k|68000).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Mac68k";
+            return cos;
+        }
+
+        p = Pattern.compile(".*(9x 4.90|Win9(5|8)|Windows 9(5|8)|95/NT|Win32|32bit).*");
+        m = p.matcher(userAgent);
+        if (m.find()) {
+            cos = "Win9x";
+            return cos;
+        }
+
+        return cos;
+    }
+
+    /**
+     * 获取浏览器版本
+     * 
+     * @param userAgent
+     * @return
+     */
+    private String getBrowser(String userAgent) {
+        userAgent = userAgent.toLowerCase();
+        String msieP = "msie ([\\d.]+)";
+        String firefoxP = "firefox\\/([\\d.]+)";
+        String chromeP = "chrome\\/([\\d.]+)";
+        String operaP = "opera.([\\d.]+)";
+        String safariP = "version\\/([\\d.]+).*safari";
+
+        Pattern pattern = Pattern.compile(msieP);
+        Matcher mat = pattern.matcher(userAgent);
+        if (mat.find()) { return mat.group(); }
+        pattern = Pattern.compile(firefoxP);
+        mat = pattern.matcher(userAgent);
+        if (mat.find()) { return mat.group(); }
+        pattern = Pattern.compile(chromeP);
+        mat = pattern.matcher(userAgent);
+        if (mat.find()) { return mat.group(); }
+        pattern = Pattern.compile(operaP);
+        mat = pattern.matcher(userAgent);
+        if (mat.find()) { return mat.group(); }
+        pattern = Pattern.compile(safariP);
+        mat = pattern.matcher(userAgent);
+        if (mat.find()) { return mat.group(); }
+        return "unknow";
+    }
+}

+ 16 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/dao/FunctionDao.java

@@ -0,0 +1,16 @@
+package com.xtframe.sec.menu.dao;
+
+import java.util.List;
+
+import com.xtframe.core.menu.entity.Function;
+import com.xtframe.sec.common.SecRepository;
+import com.xtframe.sec.menu.entity.FunctionEntity;
+
+/**
+ * 数据处理接口
+ * 
+ * @author 袁晓冬
+ */
+public interface FunctionDao extends SecRepository<FunctionEntity, String> {
+    public List<Function> findByIdInOrderBySortnoAsc(String... id);
+}

+ 54 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/dao/MenuDao.java

@@ -0,0 +1,54 @@
+package com.xtframe.sec.menu.dao;
+
+import java.util.List;
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Query;
+
+import com.xtframe.core.menu.entity.Menu;
+import com.xtframe.sec.common.SecRepository;
+import com.xtframe.sec.menu.entity.MenuEntity;
+
+/**
+ * 数据处理接口
+ * 
+ * @author 袁晓冬
+ */
+public interface MenuDao extends SecRepository<MenuEntity, String> {
+    /**
+     * 根据主键检索
+     * 
+     * @param id
+     * @return
+     */
+    public List<Menu> findByIdInOrderBySortnoAsc(String... id);
+
+    /**
+     * 根据上级菜单ID检索下级
+     * 
+     * @param pid
+     * @return
+     */
+    public List<Menu> findByPidOrderBySortnoAsc(String pid);
+
+    /**
+     * 查询业务系统下的菜单功能列表
+     * 
+     * @param systemId
+     *            业务系统id
+     * @param pageable
+     *            分页对象
+     * @return
+     */
+    @Query("select m from MenuEntity m where m.pid =?1")
+    Page<Menu> findByPid(String pid, Pageable pageable);
+
+    /**
+     * 
+     * @param pid
+     * @return
+     */
+    @Query("SELECT m from MenuEntity m  where m.pid =?1 and m.valid='Y' order by m.sortno asc")
+    public List<Menu> findValidMenusByPid(String pid);
+}

+ 112 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/entity/FunctionEntity.java

@@ -0,0 +1,112 @@
+package com.xtframe.sec.menu.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import com.fasterxml.jackson.annotation.JsonBackReference;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xtframe.core.menu.entity.Function;
+import com.xtframe.core.menu.entity.Menu;
+import com.xtframe.sec.common.BaseEntity;
+import com.xtframe.sec.utils.BooleanSerializer;
+
+@Entity
+@Table(name = "t_xtframe_func")
+public class FunctionEntity extends BaseEntity<String> implements Function {
+    /** serialVersionUID */
+    private static final long serialVersionUID = 8348826024554098314L;
+    /** UUID主键 */
+    protected String id;
+    /** 显示名称 */
+    protected String name;
+    /** 功能编码,用于权限控制 */
+    protected String code;
+    /** 图标 */
+    protected String icon;
+    /** 状态open/closed */
+    @JsonSerialize(using = BooleanSerializer.class)
+    protected Boolean valid;
+    /** 功能排序号 */
+    private int sortno;
+    /** 所属菜单 */
+    protected Menu menu;
+
+    /**
+     * 获取功能编码
+     */
+    public String getCode() {
+        return code;
+    }
+
+    /**
+     * 获取功能图标
+     */
+    public String getIcon() {
+        return icon;
+    }
+
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    @ManyToOne(fetch = FetchType.LAZY, targetEntity = MenuEntity.class)
+    @JoinColumn(name = "mid")
+    @JsonBackReference
+    public Menu getMenu() {
+        return menu;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getSortno() {
+        return sortno;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getValid() {
+        return valid;
+    }
+
+    @Override
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setMenu(Menu menu) {
+        this.menu = menu;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setSortno(int sortno) {
+        this.sortno = sortno;
+    }
+
+    public void setValid(Boolean valid) {
+        this.valid = valid;
+    }
+
+}

+ 218 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/entity/MenuEntity.java

@@ -0,0 +1,218 @@
+package com.xtframe.sec.menu.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Type;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xtframe.core.menu.entity.Menu;
+import com.xtframe.sec.common.BaseEntity;
+import com.xtframe.sec.utils.BooleanSerializer;
+
+@Entity
+@Table(name = "t_xtframe_menu")
+public class MenuEntity extends BaseEntity<String> implements Menu {
+    /** serialVersionUID */
+    private static final long serialVersionUID = 4301911065785689333L;
+    /** UUID主键 */
+    private String id;
+    /** 上级菜单UUID主键 */
+    private String pid;
+    /** 显示名称 */
+    private String name;
+    /** 菜单编码,用于权限控制 */
+    private String code;
+    /** 图标 */
+    private String icon;
+    /** 图标2,一般放大图标样式 */
+    private String icon2;
+    /** 状态open/closed */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean leaf;
+    /** 状态open/closed */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean valid;
+    /** 是否外部链接 */
+    @JsonSerialize(using = BooleanSerializer.class)
+    private Boolean outLink;
+    /** 菜单访问路径 */
+    private String url;
+    /** 菜单排序号 */
+    private int sortno;
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        MenuEntity other = (MenuEntity) obj;
+        if (code == null) {
+            if (other.code != null) return false;
+        }
+        else if (!code.equals(other.code)) return false;
+        if (icon == null) {
+            if (other.icon != null) return false;
+        }
+        else if (!icon.equals(other.icon)) return false;
+        if (id == null) {
+            if (other.id != null) return false;
+        }
+        else if (!id.equals(other.id)) return false;
+        if (leaf == null) {
+            if (other.leaf != null) return false;
+        }
+        else if (!leaf.equals(other.leaf)) return false;
+        if (name == null) {
+            if (other.name != null) return false;
+        }
+        else if (!name.equals(other.name)) return false;
+        if (pid == null) {
+            if (other.pid != null) return false;
+        }
+        else if (!pid.equals(other.pid)) return false;
+        if (sortno != other.sortno) return false;
+        if (url == null) {
+            if (other.url != null) return false;
+        }
+        else if (!url.equals(other.url)) return false;
+        if (valid == null) {
+            if (other.valid != null) return false;
+        }
+        else if (!valid.equals(other.valid)) return false;
+        return true;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    /**
+     * 获取菜单图标
+     */
+    public String getIcon() {
+        return icon;
+    }
+
+    /**
+     * 图标2,一般放大图标样式
+     * 
+     * @return
+     */
+    public String getIcon2() {
+        return icon2;
+    }
+
+    @Id
+    @GenericGenerator(name = "systemUUID", strategy = "uuid")
+    @GeneratedValue(generator = "systemUUID")
+    public String getId() {
+        return id;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getLeaf() {
+        return leaf;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getOutLink() {
+        return outLink;
+    }
+
+    public String getPid() {
+        return pid;
+    }
+
+    public int getSortno() {
+        return sortno;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    @Type(type = "yes_no")
+    public Boolean getValid() {
+        return valid;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((code == null) ? 0 : code.hashCode());
+        result = prime * result + ((icon == null) ? 0 : icon.hashCode());
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        result = prime * result + ((leaf == null) ? 0 : leaf.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((pid == null) ? 0 : pid.hashCode());
+        result = prime * result + sortno;
+        result = prime * result + ((url == null) ? 0 : url.hashCode());
+        result = prime * result + ((valid == null) ? 0 : valid.hashCode());
+        return result;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public void setIcon(String icon) {
+        this.icon = icon;
+    }
+
+    /**
+     * 图标2,一般放大图标样式
+     * 
+     * @param icon2
+     */
+    public void setIcon2(String icon2) {
+        this.icon2 = icon2;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setLeaf(Boolean leaf) {
+        this.leaf = leaf;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setOutLink(Boolean outLink) {
+        this.outLink = outLink;
+    }
+
+    public void setPid(String pid) {
+        this.pid = pid;
+    }
+
+    public void setSortno(int sortno) {
+        this.sortno = sortno;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public void setValid(Boolean valid) {
+        this.valid = valid;
+    }
+
+    @Override
+    public String toString() {
+        return "MenuEntity [id=" + id + ", pid=" + pid + ", name=" + name + ", code=" + code + ", icon=" + icon
+                + ", leaf=" + leaf + ", valid=" + valid + ", url=" + url + ", sortno=" + sortno + "]";
+    }
+
+}

+ 405 - 0
gkoa/trunk/xtframe-oa/modules/xtframe-security/src/main/java/com/xtframe/sec/menu/service/impl/MenuServiceImpl.java

@@ -0,0 +1,405 @@
+package com.xtframe.sec.menu.service.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import javax.transaction.Transactional;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.Assert;
+
+import com.xtframe.core.base.ctl.BaseCtl;
+import com.xtframe.core.base.vo.NodeVo;
+import com.xtframe.core.exception.BizException;
+import com.xtframe.core.menu.entity.Function;
+import com.xtframe.core.menu.entity.Menu;
+import com.xtframe.core.menu.service.MenuService;
+import com.xtframe.core.user.entity.User;
+import com.xtframe.sec.common.BaseSecurityService;
+import com.xtframe.sec.common.OracleSqlConsts;
+import com.xtframe.sec.menu.dao.FunctionDao;
+import com.xtframe.sec.menu.dao.MenuDao;
+import com.xtframe.sec.menu.entity.FunctionEntity;
+import com.xtframe.sec.menu.entity.MenuEntity;
+import com.xtframe.sec.utils.SecUtils;
+
+public class MenuServiceImpl extends BaseSecurityService implements MenuService {
+    private MenuDao dao;
+    private FunctionDao funcDao;
+
+    @Override
+    @Transactional
+    public String delete(String... ids) {
+        dao.delete(ids);
+        return null;
+    }
+
+    @Override
+    public void deleteOrgFunctionMap(String arg0, String... arg1) {
+        throw new BizException("不支持此方法!请与管理员联系!");
+    }
+
+    @Override
+    public void deleteOrgMenuMap(String arg0, String... arg1) {
+        throw new BizException("不支持此方法!请与管理员联系!");
+    }
+
+    @Override
+    public void deleteRoleFunctionMap(String arg0, String... arg1) {
+        throw new BizException("不支持此方法!请与管理员联系!");
+    }
+
+    @Override
+    public void deleteRoleMenuMap(String arg0, String... arg1) {
+        throw new BizException("不支持此方法!请与管理员联系!");
+    }
+
+    @Override
+    public void deleteUserMenuMap(String arg0, String... arg1) {
+        throw new BizException("不支持此方法!请与管理员联系!");
+    }
+
+    @Override
+    public List<Menu> findAccordionMenus() {
+        return findAuthedMenuByPid(BaseCtl.BLANK_UUID);
+    }
+
+    @Override
+    public List<Menu> findAuthedMenuByPid(final String pid) {
+        User u = SecUtils.getCurrUser();
+        String sql = "SELECT M.* FROM T_XTFRAME_MENU M " + "WHERE M.VALID='Y' AND M.PID=:pid AND"
+                + "( EXISTS(SELECT 1 " + "FROM T_XTFRAME_USER_MENU UM " + "WHERE UM.MID=M.ID AND UM.USERID=:userid) "
+                + "OR EXISTS( " + "SELECT 1 FROM T_XTFRAME_ROLE_MENU RM JOIN T_XTFRAME_ROLE_USER RU ON RM.RID=RU.RID "
+                + "WHERE RU.USERID=:userid AND RM.MID=M.ID) " + "OR EXISTS( "
+                + "SELECT 1 FROM T_XTFRAME_ORG_MENU OM JOIN T_XTFRAME_USER U ON OM.ORGID=U.ORG "
+                + "WHERE U.ID=:userid AND OM.MID=M.ID)) ORDER BY M.SORTNO ASC";
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("userid", u.getId());
+        params.put("pid", pid);
+        List<MenuEntity> menus = dao.nativeQuery(sql, MenuEntity.class, params);
+        List<Menu> ms = new ArrayList<Menu>(menus.size());
+        for (MenuEntity m : menus) {
+            ms.add(m);
+        }
+        return ms;
+    }
+
+    @Override
+    public Function findFunction(String id) {
+        return funcDao.findOne(id);
+    }
+
+    @Override
+    public List<Function> findFunctionByIds(String... id) {
+        return funcDao.findByIdInOrderBySortnoAsc(id);
+    }
+
+    @Override
+    public Menu findMenu(String id) {
+        return dao.findOne(id);
+    }
+
+    @Override
+    public List<Menu> findMenuByIds(String... id) {
+        return dao.findByIdInOrderBySortnoAsc(id);
+    }
+
+    public List<Function> findValidFunctionByOrgId(final String orgId) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("orgid", orgId);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder
+                .append("select f.* from T_XTFRAME_FUNC f join T_XTFRAME_ORG_FUNC ofc on f.id=ofc.fid where ofc.orgid=:orgid");
+        List<FunctionEntity> fes = funcDao.nativeQuery(sqlBuilder.toString(), FunctionEntity.class, params);
+        List<Function> fs = new ArrayList<Function>(fes.size());
+        for (FunctionEntity fe : fes) {
+            fs.add(fe);
+        }
+        return fs;
+    }
+
+    @Override
+    public List<Function> findValidFunctionByRoleId(String roleId) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("roleid", roleId);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder
+                .append("select f.* from T_XTFRAME_FUNC f join T_XTFRAME_ROLE_FUNC rfc on f.id=rfc.fid where rfc.rid=:roleid");
+        List<FunctionEntity> fes = funcDao.nativeQuery(sqlBuilder.toString(), FunctionEntity.class, params);
+        List<Function> fs = new ArrayList<Function>(fes.size());
+        for (FunctionEntity fe : fes) {
+            fs.add(fe);
+        }
+        return fs;
+    }
+
+    @Override
+    public List<Function> findValidFunctionByUserId(String userId) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("userid", userId);
+        List<FunctionEntity> fes = funcDao.nativeQuery(OracleSqlConsts.queryFunctionByUser, FunctionEntity.class,
+                params);
+        List<Function> fs = new ArrayList<Function>(fes.size());
+        for (FunctionEntity fe : fes) {
+            fs.add(fe);
+        }
+        return fs;
+    }
+
+    public List<Menu> findValidMenuByOrgId(final String orgId) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("orgid", orgId);
+        List<MenuEntity> mes = dao.nativeQuery(
+                "select m.* from T_XTFRAME_MENU m join T_XTFRAME_ORG_MENU om on m.id=om.mid where om.orgid=:orgid",
+                MenuEntity.class, params);
+        List<Menu> ms = new ArrayList<Menu>(mes.size());
+        for (MenuEntity me : mes) {
+            ms.add(me);
+        }
+        return ms;
+    }
+
+    public List<Menu> findValidMenuByPid(final String pid) {
+        return dao.findValidMenusByPid(pid);
+    }
+
+    @Override
+    public List<Menu> findValidMenuByRoleId(String roleId) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("roleid", roleId);
+        List<MenuEntity> mes = dao.nativeQuery(
+                "select m.* from T_XTFRAME_MENU m join T_XTFRAME_ROLE_MENU rm on m.id=rm.mid where rm.rid=:roleid",
+                MenuEntity.class, params);
+        List<Menu> ms = new ArrayList<Menu>(mes.size());
+        for (MenuEntity me : mes) {
+            ms.add(me);
+        }
+        return ms;
+    }
+
+    @Override
+    public List<Menu> findValidMenuByUserId(String userid) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("userid", userid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder
+                .append("select m.* from T_XTFRAME_MENU m join T_XTFRAME_USER_MENU um on m.id=um.mid where um.userid=:userid");
+        List<MenuEntity> mes = dao.nativeQuery(sqlBuilder.toString(), MenuEntity.class, params);
+        List<Menu> ms = new ArrayList<Menu>(mes.size());
+        for (MenuEntity me : mes) {
+            ms.add(me);
+        }
+        return ms;
+    }
+
+    /**
+     * 根据上级菜单ID和授权菜单列表获取下级菜单节点
+     * 
+     * @param pid
+     *            上级菜单ID
+     * @param authedMenus
+     *            授权菜单列表
+     * @param cascade
+     *            是否级联获取下级
+     * @return
+     */
+    public List<NodeVo> getCheckedMenusByPid(String pid, Collection<Menu> authedMenus,
+            Collection<Function> authedFuncs, boolean cascade) {
+        List<NodeVo> menuVos = new ArrayList<NodeVo>();
+        List<Menu> menus = securityMgr.findValidMenusByPid(pid);
+        // 循环生成节点对象
+        for (Menu m : menus) {
+            if (m instanceof MenuEntity) {
+                NodeVo mv = new NodeVo();
+                mv.setId(m.getId());
+                mv.setText(m.getName());
+                mv.setParent(m.getPid());
+                mv.setState("closed");
+                if (authedMenus.contains(m)) {
+                    mv.setChecked(true);
+                }
+                else {
+                    mv.setChecked(false);
+                }
+                Map<String, String> attr = new HashMap<String, String>();
+                attr.put("url", m.getUrl());
+                attr.put("leaf", String.valueOf(m.getLeaf()));
+                attr.put("type", "menu");
+
+                if (m.getLeaf()) {
+                    attr.put("funcs", getFunctionByMenu(m.getId(), authedFuncs).toString());
+                    mv.setState("open");
+                }
+                else {
+                    if (cascade) { // 非叶子节点且需要级联时
+                        mv.setChildren(getCheckedMenusByPid(mv.getId(), authedMenus, authedFuncs, cascade));
+                    }
+                }
+                mv.setAttributes(attr);
+                menuVos.add(mv);
+            }
+        }
+        return menuVos;
+    }
+
+    /**
+     * 根据菜单获取菜单功能
+     * 
+     * @param mid
+     * @param authedFuncs
+     * @return
+     */
+    public JSONArray getFunctionByMenu(final String mid, Collection<Function> authedFuncs) {
+        Specification<FunctionEntity> spec = new Specification<FunctionEntity>() {
+            @Override
+            public Predicate toPredicate(Root<FunctionEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
+                List<Predicate> list = new ArrayList<Predicate>();
+                list.add(cb.equal(root.get("menu").get("id").as(String.class), mid));
+                return cb.and(list.toArray(new Predicate[] {}));
+            }
+        };
+        List<FunctionEntity> funcList = funcDao.findAll(spec);
+        JSONArray arr = new JSONArray();
+        for (FunctionEntity f : funcList) {
+            JSONObject jo = new JSONObject();
+            jo.put("id", f.getId());
+            jo.put("name", f.getName());
+            if (authedFuncs.contains(f)) {
+                jo.put("checked", true);
+            }
+            else {
+                jo.put("checked", false);
+            }
+            arr.add(jo);
+        }
+        return arr;
+    }
+
+    @Override
+    public void init() {
+        this.dao = (MenuDao) getBeans().get("menuDao");
+        this.funcDao = (FunctionDao) getBeans().get("functionDao");
+        Assert.notNull(this.dao);
+    }
+
+    @Override
+    @Transactional
+    public Menu save(Menu menu) {
+        if (menu instanceof MenuEntity) { return dao.save((MenuEntity) menu); }
+        return null;
+    }
+
+    @Override
+    @Transactional
+    public Function saveFunction(Function f) {
+        if (f instanceof FunctionEntity) { return funcDao.save((FunctionEntity) f); }
+        return null;
+    }
+
+    @Override
+    public void saveOrgFunctionMap(String orgid, String... funcIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("orgid", orgid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_ORG_FUNC where orgid=:orgid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_ORG_FUNC(orgid,fid)values(:orgid,:fid) ");
+        for (String fid : funcIds) {
+            params.put("fid", fid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+    @Override
+    @Transactional
+    public void saveOrgMenuMap(String orgId, String... menuIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("orgid", orgId);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_ORG_MENU where orgid=:orgid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_ORG_MENU(orgid,mid)values(:orgid,:mid) ");
+        for (String mid : menuIds) {
+            params.put("mid", mid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+    @Override
+    public void saveRoleFunctionMap(String roleid, String... funcIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("roleid", roleid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_ROLE_FUNC where rid=:roleid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_ROLE_FUNC(rid,fid)values(:roleid,:fid) ");
+        for (String fid : funcIds) {
+            params.put("fid", fid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+    @Override
+    public void saveRoleMenuMap(String roleid, String... menuIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("roleid", roleid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_ROLE_MENU where rid=:roleid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_ROLE_MENU(rid,mid)values(:roleid,:mid) ");
+        for (String mid : menuIds) {
+            params.put("mid", mid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+    /**
+     * 保存用户功能映射关系
+     * 
+     * @param userid
+     * @param funcIds
+     */
+    public void saveUserFunctionMap(String userid, String... funcIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("userid", userid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_USER_FUNC where userid=:userid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_USER_FUNC(userid,fid)values(:userid,:fid) ");
+        for (String fid : funcIds) {
+            params.put("fid", fid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+    @Override
+    public void saveUserMenuMap(String userid, String... menuIds) {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("userid", userid);
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("delete from T_XTFRAME_USER_MENU where userid=:userid");
+        dao.nativeUpdate(sqlBuilder.toString(), params);
+        sqlBuilder.setLength(0);
+        sqlBuilder.append("insert into T_XTFRAME_USER_MENU(userid,mid)values(:userid,:mid) ");
+        for (String mid : menuIds) {
+            params.put("mid", mid);
+            dao.nativeUpdate(sqlBuilder.toString(), params);
+        }
+    }
+
+}

Some files were not shown because too many files changed in this diff