Bläddra i källkod

添加调试信息输出到文件功能,这样通过浏览文件或访问URL即可查看调试信息输出

jacky6024 8 år sedan
förälder
incheckning
7040894648
53 ändrade filer med 574 tillägg och 39 borttagningar
  1. 43 0
      urule-console/src/main/java/com/bstek/urule/console/servlet/console/ConsoleDebugWriter.java
  2. 65 0
      urule-console/src/main/java/com/bstek/urule/console/servlet/console/ConsoleServletHandler.java
  3. 35 0
      urule-console/src/main/java/com/bstek/urule/console/servlet/console/DebugMessage.java
  4. 64 0
      urule-console/src/main/java/com/bstek/urule/console/servlet/console/DebugMessageHolder.java
  5. 1 0
      urule-console/src/main/java/com/bstek/urule/console/servlet/respackage/PackageServletHandler.java
  6. 11 0
      urule-console/src/main/resources/html/console.html
  7. 0 0
      urule-console/src/main/resources/urule-asserts/js/actionEditor.bundle.js
  8. 0 0
      urule-console/src/main/resources/urule-asserts/js/clientConfigEditor.bundle.js
  9. 0 0
      urule-console/src/main/resources/urule-asserts/js/constantEditor.bundle.js
  10. 0 0
      urule-console/src/main/resources/urule-asserts/js/decisionTableEditor.bundle.js
  11. 0 0
      urule-console/src/main/resources/urule-asserts/js/decisionTreeEditor.bundle.js
  12. 0 0
      urule-console/src/main/resources/urule-asserts/js/flowDesigner.bundle.js
  13. 0 0
      urule-console/src/main/resources/urule-asserts/js/frame.bundle.js
  14. 0 0
      urule-console/src/main/resources/urule-asserts/js/packageEditor.bundle.js
  15. 0 0
      urule-console/src/main/resources/urule-asserts/js/parameterEditor.bundle.js
  16. 0 0
      urule-console/src/main/resources/urule-asserts/js/permissionConfigEditor.bundle.js
  17. 0 0
      urule-console/src/main/resources/urule-asserts/js/ruleSetEditor.bundle.js
  18. 0 0
      urule-console/src/main/resources/urule-asserts/js/scoreCardTable.bundle.js
  19. 0 0
      urule-console/src/main/resources/urule-asserts/js/scriptDecisionTableEditor.bundle.js
  20. 0 0
      urule-console/src/main/resources/urule-asserts/js/ulEditor.bundle.js
  21. 0 0
      urule-console/src/main/resources/urule-asserts/js/variableEditor.bundle.js
  22. 10 0
      urule-console/src/main/resources/urule-console-context.xml
  23. 16 0
      urule-core/src/main/java/com/bstek/urule/Utils.java
  24. 5 3
      urule-core/src/main/java/com/bstek/urule/action/ConsolePrintAction.java
  25. 3 1
      urule-core/src/main/java/com/bstek/urule/action/ExecuteCommonFunctionAction.java
  26. 5 2
      urule-core/src/main/java/com/bstek/urule/action/ExecuteMethodAction.java
  27. 3 1
      urule-core/src/main/java/com/bstek/urule/action/VariableAssignAction.java
  28. 1 0
      urule-core/src/main/java/com/bstek/urule/builder/KnowledgeBuilder.java
  29. 3 0
      urule-core/src/main/java/com/bstek/urule/builder/resource/ScorecardResourceBuilder.java
  30. 28 0
      urule-core/src/main/java/com/bstek/urule/debug/DebugWriter.java
  31. 39 0
      urule-core/src/main/java/com/bstek/urule/debug/DefaultHtmlFileDebugWriter.java
  32. 65 0
      urule-core/src/main/java/com/bstek/urule/debug/MessageItem.java
  33. 24 0
      urule-core/src/main/java/com/bstek/urule/debug/MsgType.java
  34. 1 1
      urule-core/src/main/java/com/bstek/urule/model/flow/BindingNode.java
  35. 1 1
      urule-core/src/main/java/com/bstek/urule/model/flow/Connection.java
  36. 3 4
      urule-core/src/main/java/com/bstek/urule/model/flow/FlowNode.java
  37. 3 2
      urule-core/src/main/java/com/bstek/urule/model/flow/ins/FlowContextImpl.java
  38. 1 1
      urule-core/src/main/java/com/bstek/urule/model/rule/loop/LoopRule.java
  39. 7 0
      urule-core/src/main/java/com/bstek/urule/model/scorecard/ScorecardDefinition.java
  40. 17 4
      urule-core/src/main/java/com/bstek/urule/model/scorecard/runtime/ScoreRule.java
  41. 11 3
      urule-core/src/main/java/com/bstek/urule/model/scorecard/runtime/ScorecardImpl.java
  42. 4 0
      urule-core/src/main/java/com/bstek/urule/parse/scorecard/ScorecardParser.java
  43. 9 0
      urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSession.java
  44. 17 1
      urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSessionFactory.java
  45. 25 5
      urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSessionImpl.java
  46. 6 0
      urule-core/src/main/java/com/bstek/urule/runtime/rete/Context.java
  47. 25 1
      urule-core/src/main/java/com/bstek/urule/runtime/rete/ContextImpl.java
  48. 4 3
      urule-core/src/main/java/com/bstek/urule/runtime/rete/CriteriaActivity.java
  49. 4 2
      urule-core/src/main/java/com/bstek/urule/runtime/rete/EvaluationContextImpl.java
  50. 4 2
      urule-core/src/main/java/com/bstek/urule/runtime/rete/NamedCriteriaActivity.java
  51. 4 2
      urule-core/src/main/java/com/bstek/urule/runtime/rete/TerminalActivity.java
  52. 2 0
      urule-core/src/main/resources/urule-core-context.properties
  53. 5 0
      urule-core/src/main/resources/urule-core-context.xml

+ 43 - 0
urule-console/src/main/java/com/bstek/urule/console/servlet/console/ConsoleDebugWriter.java

@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.console.servlet.console;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.bstek.urule.debug.DebugWriter;
+import com.bstek.urule.debug.MessageItem;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月28日
+ */
+public class ConsoleDebugWriter implements DebugWriter {
+	private DebugMessageHolder debugMessageHolder;
+	@Override
+	public void write(List<MessageItem> items) throws IOException {
+		StringBuilder sb=new StringBuilder();
+		for(MessageItem item:items){
+			sb.append(item.toHtml());
+		}
+		String key=debugMessageHolder.generateKey();
+		System.out.println("Console key : "+key);
+		debugMessageHolder.putDebugMessage(key, sb.toString());
+	}
+	public void setDebugMessageHolder(DebugMessageHolder debugMessageHolder) {
+		this.debugMessageHolder = debugMessageHolder;
+	}
+}

+ 65 - 0
urule-console/src/main/java/com/bstek/urule/console/servlet/console/ConsoleServletHandler.java

@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.console.servlet.console;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+
+import com.bstek.urule.console.servlet.RenderPageServletHandler;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月28日
+ */
+public class ConsoleServletHandler extends RenderPageServletHandler {
+	private DebugMessageHolder debugMessageHolder;
+	@Override
+	public void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+		String key=req.getParameter("key");
+		String msg=null;
+		if(StringUtils.isBlank(key)){
+			msg="<h2 style='color:red'>请指定要查看的调试消息的key值</h2>";
+		}else{
+			msg=debugMessageHolder.getDebugMessage(key);
+		}
+		VelocityContext context = new VelocityContext();
+		context.put("title", "URule Console");
+		context.put("msg", msg);
+		resp.setContentType("text/html");
+		resp.setCharacterEncoding("utf-8");
+		Template template=ve.getTemplate("html/console.html","utf-8");
+		PrintWriter writer=resp.getWriter();
+		template.merge(context, writer);
+		writer.close();
+	}
+	
+	public void setDebugMessageHolder(DebugMessageHolder debugMessageHolder) {
+		this.debugMessageHolder = debugMessageHolder;
+	}
+
+	@Override
+	public String url() {
+		return "/console";
+	}
+}

+ 35 - 0
urule-console/src/main/java/com/bstek/urule/console/servlet/console/DebugMessage.java

@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.console.servlet.console;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月28日
+ */
+public class DebugMessage {
+	private String message;
+	private long timestamp;
+	public DebugMessage(String message) {
+		this.message=message;
+		this.timestamp=System.currentTimeMillis();
+	}
+	public String getMessage() {
+		return message;
+	}
+	public long getTimestamp() {
+		return timestamp;
+	}
+}

+ 64 - 0
urule-console/src/main/java/com/bstek/urule/console/servlet/console/DebugMessageHolder.java

@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.console.servlet.console;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月28日
+ */
+public class DebugMessageHolder {
+	private int num=0;
+	private Map<String,DebugMessage> messageMap=new HashMap<String,DebugMessage>();
+	public String getDebugMessage(String key){
+		DebugMessage msg=messageMap.get(key);
+		String info=null;
+		if(msg==null){
+			info="<h2 style='color:red'>Key为["+key+"]的调试信息已失效,不能查看,当前key值为:"+this.num+"。<br>调试消息有效期为3分钟,请在有效期内查看!</h2>";
+		}else{
+			info=msg.getMessage();
+		}
+		clean();
+		return info;
+	}
+	public void putDebugMessage(String key,String msg){
+		clean();
+		DebugMessage m=new DebugMessage(msg);
+		messageMap.put(key, m);
+	}
+	private void clean(){
+		long current=System.currentTimeMillis();
+		List<String> list=new ArrayList<String>();
+		for(String key:messageMap.keySet()){
+			DebugMessage msg=messageMap.get(key);
+			long dif=current-msg.getTimestamp();
+			if(dif>180000){
+				list.add(key);
+			}
+		}
+		for(String key:list){
+			messageMap.remove(key);
+		}
+	}
+	public synchronized String generateKey(){
+		num++;
+		return String.valueOf(num);
+	}
+}

+ 1 - 0
urule-console/src/main/java/com/bstek/urule/console/servlet/respackage/PackageServletHandler.java

@@ -699,6 +699,7 @@ public class PackageServletHandler extends RenderPageServletHandler {
 		}
 		long end=System.currentTimeMillis();
 		long elapse=end-start;
+		session.writeLogFile();
 		ExecutionResponseImpl res=(ExecutionResponseImpl)response;
 		List<RuleInfo> firedRules=res.getFiredRules();
 		List<RuleInfo> matchedRules=res.getMatchedRules();

+ 11 - 0
urule-console/src/main/resources/html/console.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>${title}</title>
+</head>
+<body style='font-size:12px'>
+${msg}
+<script type="text/javascript" src="${contextPath}/urule/res/urule-asserts/js/frame.bundle.js"></script>
+</body>
+</html>

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/actionEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/clientConfigEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/constantEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/decisionTableEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/decisionTreeEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/flowDesigner.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/frame.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/packageEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/parameterEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/permissionConfigEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/ruleSetEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/scoreCardTable.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/scriptDecisionTableEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/ulEditor.bundle.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
urule-console/src/main/resources/urule-asserts/js/variableEditor.bundle.js


+ 10 - 0
urule-console/src/main/resources/urule-console-context.xml

@@ -11,6 +11,16 @@
 		<property name="repositoryService" ref="urule.repositoryService"></property>
 	</bean>
 	
+	<bean id="urule.consoleServletHandler" class="com.bstek.urule.console.servlet.console.ConsoleServletHandler">
+		<property name="debugMessageHolder" ref="urule.debugMessageHolder"></property>
+	</bean>
+	
+	<bean id="urule.consoleDebugWriter" class="com.bstek.urule.console.servlet.console.ConsoleDebugWriter">
+		<property name="debugMessageHolder" ref="urule.debugMessageHolder"></property>
+	</bean>
+	
+	<bean id="urule.debugMessageHolder" class="com.bstek.urule.console.servlet.console.DebugMessageHolder"></bean>
+	
 	<bean id="urule.httpSessionKnowledgeCache" class="com.bstek.urule.console.servlet.respackage.HttpSessionKnowledgeCache"></bean>
 	
 	<bean id="urule.repositoryResourceProvider" class="com.bstek.urule.console.repository.RepositoryResourceProvider">

+ 16 - 0
urule-core/src/main/java/com/bstek/urule/Utils.java

@@ -33,6 +33,7 @@ import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 
+import com.bstek.urule.debug.DebugWriter;
 import com.bstek.urule.model.function.FunctionDescriptor;
 import com.bstek.urule.model.library.Datatype;
 
@@ -42,7 +43,9 @@ import com.bstek.urule.model.library.Datatype;
  */
 public class Utils implements ApplicationContextAware{
 	private static boolean debug;
+	private static boolean debugToFile;
 	private static ApplicationContext applicationContext;
+	private static Collection<DebugWriter> debugWriters;
 	private static Map<String,FunctionDescriptor> functionDescriptorMap=new HashMap<String,FunctionDescriptor>();
 	private static Map<String,FunctionDescriptor> functionDescriptorLabelMap=new HashMap<String,FunctionDescriptor>();
 	public static ApplicationContext getApplicationContext() {
@@ -186,10 +189,22 @@ public class Utils implements ApplicationContextAware{
 		Utils.debug = debug;
 	}
 	
+	public void setDebugToFile(boolean debugToFile) {
+		Utils.debugToFile = debugToFile;
+	}
+	
+	public static boolean isDebugToFile() {
+		return debugToFile;
+	}
+	
 	public static boolean isDebug() {
 		return debug;
 	}
 	
+	public static Collection<DebugWriter> getDebugWriters() {
+		return debugWriters;
+	}
+	
 	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 		Collection<FunctionDescriptor> functionDescriptors=applicationContext.getBeansOfType(FunctionDescriptor.class).values();
 		for(FunctionDescriptor fun:functionDescriptors){
@@ -202,6 +217,7 @@ public class Utils implements ApplicationContextAware{
 			functionDescriptorMap.put(fun.getName(), fun);
 			functionDescriptorLabelMap.put(fun.getLabel(), fun);
 		}
+		debugWriters=applicationContext.getBeansOfType(DebugWriter.class).values();
 		Utils.applicationContext=applicationContext;
 		new Splash().print();
 	}

+ 5 - 3
urule-core/src/main/java/com/bstek/urule/action/ConsolePrintAction.java

@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.rule.Value;
 import com.bstek.urule.runtime.rete.Context;
 import com.bstek.urule.runtime.rete.ValueCompute;
@@ -39,12 +40,13 @@ public class ConsolePrintAction extends AbstractAction {
 		Object content=valueCompute.complexValueCompute(value, matchedObject, context,allMatchedObjects,variableMap);
 		if(content instanceof BigDecimal){
 			BigDecimal b=(BigDecimal)content;
-			System.out.println(b.floatValue());
+			context.debugMsg("☢☢☢控制台输出:"+b.toPlainString(), MsgType.ConsoleOutput, true);
 		}else if(content instanceof Double){
 			Double d=(Double)content;
-			System.out.println(d.floatValue());
+			context.debugMsg("☢☢☢控制台输出:"+d.toString(), MsgType.ConsoleOutput, true);
 		}else{
-			System.out.println(content);
+			String msg=(content==null ? "null" : content.toString());
+			context.debugMsg("☢☢☢控制台输出:"+msg, MsgType.ConsoleOutput, true);
 		}
 		return null;
 	}

+ 3 - 1
urule-core/src/main/java/com/bstek/urule/action/ExecuteCommonFunctionAction.java

@@ -20,6 +20,7 @@ import java.util.Map;
 
 import com.bstek.urule.RuleException;
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.function.FunctionDescriptor;
 import com.bstek.urule.model.rule.Value;
 import com.bstek.urule.model.rule.lhs.CommonFunctionParameter;
@@ -58,7 +59,8 @@ public class ExecuteCommonFunctionAction extends AbstractAction{
 		Object result=function.doFunction(object, property,context.getWorkingMemory());
 		if(debug && Utils.isDebug()){
 			info=info+(object==null ? "" : object);
-			System.out.println("***执行函数:"+info);
+			String msg="***执行函数:"+info;
+			context.debugMsg(msg, MsgType.ExecuteFunction, debug);
 		}
 		if(result!=null){
 			return new ActionValueImpl(name,result);					

+ 5 - 2
urule-core/src/main/java/com/bstek/urule/action/ExecuteMethodAction.java

@@ -25,6 +25,7 @@ import java.util.Set;
 
 import com.bstek.urule.RuleException;
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.library.Datatype;
 import com.bstek.urule.model.rule.Parameter;
 import com.bstek.urule.runtime.rete.Context;
@@ -84,7 +85,8 @@ public class ExecuteMethodAction extends AbstractAction {
 				}
 				Object value=method.invoke(obj, wrap.getValues());
 				if(debug && Utils.isDebug()){
-					System.out.println(info+"("+wrap.valuesToString()+")");
+					String msg=info+"("+wrap.valuesToString()+")";
+					context.debugMsg(msg, MsgType.ExecuteBeanMethod, debug);
 				}
 				if(value!=null){
 					return new ActionValueImpl(valueKey,value);					
@@ -100,7 +102,8 @@ public class ExecuteMethodAction extends AbstractAction {
 				}
 				Object value=method.invoke(obj);
 				if(debug && Utils.isDebug()){
-					System.out.println(info+"()");
+					String msg=info+"()";
+					context.debugMsg(msg, MsgType.ExecuteBeanMethod, debug);
 				}
 				if(value!=null){
 					return new ActionValueImpl(valueKey,value);					

+ 3 - 1
urule-core/src/main/java/com/bstek/urule/action/VariableAssignAction.java

@@ -25,6 +25,7 @@ import org.springframework.beans.BeanUtils;
 
 import com.bstek.urule.RuleException;
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.library.Datatype;
 import com.bstek.urule.model.rule.Value;
 import com.bstek.urule.model.rule.lhs.LeftType;
@@ -87,7 +88,8 @@ public class VariableAssignAction extends AbstractAction {
 		}
 		Utils.setObjectProperty(targetFact, propertyName, obj);
 		if(debug && Utils.isDebug()){
-			System.out.println("###变量赋值:"+label+"="+obj);
+			String msg="###变量赋值:"+label+"="+obj;
+			context.debugMsg(msg, MsgType.VarAssign, debug);
 		}
 		return null;
 	}

+ 1 - 0
urule-core/src/main/java/com/bstek/urule/builder/KnowledgeBuilder.java

@@ -147,6 +147,7 @@ public class KnowledgeBuilder extends AbstractBuilder{
 	
 	private List<Rule> buildRules(LoopRule loopRule){
 		Rule rule=new Rule();
+		rule.setDebug(loopRule.getDebug());
 		rule.setName("loop-rule");
 		rule.setLhs(loopRule.getLhs());
 		rule.setRhs(loopRule.getRhs());

+ 3 - 0
urule-core/src/main/java/com/bstek/urule/builder/resource/ScorecardResourceBuilder.java

@@ -66,6 +66,7 @@ public class ScorecardResourceBuilder implements ResourceBuilder<ScoreRule> {
 		scoreRule.setExpiresDate(scorecard.getExpiresDate());
 		scoreRule.setEnabled(scorecard.getEnabled());
 		scoreRule.setSalience(scorecard.getSalience());
+		scoreRule.setDebug(scorecard.getDebug());
 
 		scoreRule.setScoringBean(scorecard.getScoringBean());
 		scoreRule.setScoringType(scorecard.getScoringType());
@@ -87,9 +88,11 @@ public class ScorecardResourceBuilder implements ResourceBuilder<ScoreRule> {
 			int attributeRowNumber=row.getRowNumber();
 			Rule rule = buildRule(cells, customCols,attributeVariableCategory, attributeRowNumber,attributeRowNumber);
 			rules.add(rule);
+			rule.setDebug(scorecard.getDebug());
 			for(ConditionRow conditionRow:conditionRows){
 				int conditionRowNumber=conditionRow.getRowNumber();
 				Rule r = buildRule(cells,customCols,attributeVariableCategory,attributeRowNumber,conditionRowNumber);
+				r.setDebug(scorecard.getDebug());
 				rules.add(r);
 			}
 		}

+ 28 - 0
urule-core/src/main/java/com/bstek/urule/debug/DebugWriter.java

@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.debug;
+
+import java.io.IOException;
+import java.util.List;
+
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月27日
+ */
+public interface DebugWriter {
+	void write(List<MessageItem> items) throws IOException;
+}

+ 39 - 0
urule-core/src/main/java/com/bstek/urule/debug/DefaultHtmlFileDebugWriter.java

@@ -0,0 +1,39 @@
+package com.bstek.urule.debug;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月27日
+ */
+public class DefaultHtmlFileDebugWriter implements DebugWriter{
+	private String path;
+	@Override
+	public void write(List<MessageItem> items) throws IOException{
+		if(StringUtils.isBlank(path)){
+			return;
+		}
+		StringBuilder msg=new StringBuilder();
+		for(MessageItem item:items){
+			msg.append(item.toHtml());
+		}
+		String fullPath=path+"/urule-debug.html";
+		StringBuilder sb=new StringBuilder();
+		sb.append("<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>URule调试日志信息</title><body style='font-size:12px'>");
+		sb.append(msg.toString());
+		sb.append("</body></html>");
+		FileOutputStream out=new FileOutputStream(new File(fullPath));
+		IOUtils.write(sb.toString(), out);
+		out.flush();
+		out.close();
+	}
+	public void setPath(String path) {
+		this.path = path;
+	}
+}

+ 65 - 0
urule-core/src/main/java/com/bstek/urule/debug/MessageItem.java

@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.debug;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月27日
+ */
+public class MessageItem {
+	private String msg;
+	private MsgType type;
+	public MessageItem(String msg,MsgType type) {
+		this.msg=msg;			
+		this.type=type;
+	}
+	public String toHtml(){
+		String color="#000";
+		switch(type){
+		case Condition:
+			color="#6495ED";
+			break;
+		case ConsoleOutput:
+			color="#000";
+			break;
+		case ExecuteBeanMethod:
+			color="#8A2BE2";
+			break;
+		case ExecuteFunction:
+			color="#008B8B";
+			break;
+		case RuleFlow:
+			color="#9932CC";
+			break;
+		case VarAssign:
+			color="#FF7F50";
+			break;
+		case ScoreCard:
+			color="#40E0D0";
+			break;
+		case RuleMatch:
+			color="#666600";
+			break;
+		}
+		return "<div style=\"color:"+color+";margin:2px\">"+msg+"</div>";
+	}
+	public String getMsg() {
+		return msg;
+	}
+	public MsgType getType() {
+		return type;
+	}
+}

+ 24 - 0
urule-core/src/main/java/com/bstek/urule/debug/MsgType.java

@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright 2017 Bstek
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.  You may obtain a copy
+ * of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ ******************************************************************************/
+package com.bstek.urule.debug;
+
+/**
+ * @author Jacky.gao
+ * @since 2017年11月27日
+ */
+public enum MsgType {
+	Condition,VarAssign,ExecuteBeanMethod,ExecuteFunction,ConsoleOutput,RuleFlow,ScoreCard,RuleMatch
+}

+ 1 - 1
urule-core/src/main/java/com/bstek/urule/model/flow/BindingNode.java

@@ -44,7 +44,7 @@ public abstract class BindingNode extends FlowNode {
 		KnowledgeSession parentSession=(KnowledgeSession)context.getWorkingMemory();
 		List<Object> facts=parentSession.getAllFacts();
 		KnowledgePackage knowledgePackage=knowledgePackageWrapper.getKnowledgePackage();
-		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);
+		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage,context.getDebugMessageItems());
 		for(Object fact:facts){
 			session.insert(fact);
 		}

+ 1 - 1
urule-core/src/main/java/com/bstek/urule/model/flow/Connection.java

@@ -46,7 +46,7 @@ public class Connection {
 		}
 		KnowledgeSession parentSession=(KnowledgeSession)context.getWorkingMemory();
 		List<Object> facts=parentSession.getAllFacts();
-		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage());
+		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage(),context.getDebugMessageItems());
 		for(Object fact:facts){
 			session.insert(fact);
 		}

+ 3 - 4
urule-core/src/main/java/com/bstek/urule/model/flow/FlowNode.java

@@ -20,7 +20,7 @@ import java.util.List;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.context.ApplicationContext;
 
-import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.Node;
 import com.bstek.urule.model.flow.ins.FlowContext;
 import com.bstek.urule.model.flow.ins.FlowInstance;
@@ -49,9 +49,8 @@ public abstract class FlowNode implements Node{
 		this.name=name;
 	}
 	public final void enter(FlowContext context,FlowInstance instance){
-		if(instance.isDebug() && Utils.isDebug()){
-			System.out.println(">>>进入决策流节点:"+name);
-		}
+		String msg=">>>进入决策流节点:"+name;
+		context.debugMsg(msg, MsgType.RuleFlow, instance.isDebug());
 		((ExecutionResponseImpl)context.getResponse()).addNodeName(name);
 		KnowledgeSession session=(KnowledgeSession)context.getWorkingMemory();
 		session.fireEvent(new ProcessBeforeNodeTriggeredEventImpl(this,instance,session));

+ 3 - 2
urule-core/src/main/java/com/bstek/urule/model/flow/ins/FlowContextImpl.java

@@ -22,6 +22,7 @@ import java.util.Map;
 
 import org.springframework.context.ApplicationContext;
 
+import com.bstek.urule.debug.MessageItem;
 import com.bstek.urule.runtime.WorkingMemory;
 import com.bstek.urule.runtime.response.ExecutionResponseImpl;
 import com.bstek.urule.runtime.response.FlowExecutionResponse;
@@ -36,8 +37,8 @@ public class FlowContextImpl extends ContextImpl implements FlowContext {
 	private Map<String,Object> sessionValueMap;
 	private List<FlowInstance> flowInstances=new ArrayList<FlowInstance>();
 	private ExecutionResponseImpl response;
-	public FlowContextImpl(WorkingMemory workingMemory,Map<String,String> variableCategoryMap,ApplicationContext applicationContext) {
-		super(workingMemory,applicationContext,variableCategoryMap);
+	public FlowContextImpl(WorkingMemory workingMemory,Map<String,String> variableCategoryMap,ApplicationContext applicationContext,List<MessageItem> debugMessageItems) {
+		super(workingMemory,applicationContext,variableCategoryMap,debugMessageItems);
 		sessionValueMap=new HashMap<String,Object>();
 	}
 	

+ 1 - 1
urule-core/src/main/java/com/bstek/urule/model/rule/loop/LoopRule.java

@@ -76,7 +76,7 @@ public class LoopRule extends Rule{
 			}
 		}
 
-		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage());
+		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage(),context.getDebugMessageItems());
 		if(loopTargetObj instanceof Collection){
 			Collection<?> collections=(Collection<?>)loopTargetObj;
 			String loopClazz=null;

+ 7 - 0
urule-core/src/main/java/com/bstek/urule/model/scorecard/ScorecardDefinition.java

@@ -32,6 +32,7 @@ public class ScorecardDefinition {
 	private Date effectiveDate;
 	private Date expiresDate;
 	private Boolean enabled;
+	private Boolean debug;
 	
 	private String attributeColName;
 	private String attributeColWidth;
@@ -90,6 +91,12 @@ public class ScorecardDefinition {
 	public void setEnabled(Boolean enabled) {
 		this.enabled = enabled;
 	}
+	public Boolean getDebug() {
+		return debug;
+	}
+	public void setDebug(Boolean debug) {
+		this.debug = debug;
+	}
 	public String getAttributeColName() {
 		return attributeColName;
 	}

+ 17 - 4
urule-core/src/main/java/com/bstek/urule/model/scorecard/runtime/ScoreRule.java

@@ -27,6 +27,7 @@ import org.codehaus.jackson.annotate.JsonIgnore;
 import com.bstek.urule.RuleException;
 import com.bstek.urule.Utils;
 import com.bstek.urule.action.ActionValue;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.library.Datatype;
 import com.bstek.urule.model.rule.Library;
 import com.bstek.urule.model.rule.Rule;
@@ -58,10 +59,14 @@ public class ScoreRule extends Rule{
 	public List<ActionValue> execute(Context context,Object matchedObject,List<Object> allMatchedObjects,Map<String,Object> variableMap){
 		KnowledgeSession parentSession=(KnowledgeSession)context.getWorkingMemory();
 		List<Object> facts=parentSession.getAllFacts();
-		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage());
+		KnowledgeSession session=KnowledgeSessionFactory.newKnowledgeSession(knowledgePackageWrapper.getKnowledgePackage(),context.getDebugMessageItems());
 		for(Object fact:facts){
 			session.insert(fact);
 		}
+		boolean isdebug=false;
+		if(this.getDebug()!=null){
+			isdebug=this.getDebug();
+		}
 		List<ActionValue> values=session.fireRules(parentSession.getParameters()).getActionValues();
 		Map<Integer,RowItemImpl> rowMap=new HashMap<Integer,RowItemImpl>();
 		for(ActionValue value:values){
@@ -70,6 +75,10 @@ public class ScoreRule extends Rule{
 			}
 			ScoreRuntimeValue scoreValue=(ScoreRuntimeValue)value.getValue();
 			int rowNumber=scoreValue.getRowNumber();
+			if(isdebug && Utils.isDebug()){
+				String msg="---行"+rowNumber+",得分:"+scoreValue.getValue();
+				context.debugMsg(msg, MsgType.ScoreCard, isdebug);
+			}
 			RowItemImpl rowItem=null;
 			if(rowMap.containsKey(rowNumber)){
 				rowItem=rowMap.get(rowNumber);
@@ -88,13 +97,17 @@ public class ScoreRule extends Rule{
 		}
 		List<RowItem> items=new ArrayList<RowItem>();
 		items.addAll(rowMap.values());
-		ScorecardImpl card=new ScorecardImpl(getName(),items);
+		ScorecardImpl card=new ScorecardImpl(getName(),items,isdebug);
 		Object actualScore=null;
 		if(scoringType.equals(ScoringType.sum)){
-			actualScore=card.executeSum();
+			actualScore=card.executeSum(context);
 		}else if(scoringType.equals(ScoringType.weightsum)){
-			actualScore=card.executeWeightSum();
+			actualScore=card.executeWeightSum(context);
 		}else if(scoringType.equals(ScoringType.custom)){
+			if(isdebug && Utils.isDebug()){
+				String msg="---执行自定义评分卡得分计算Bean:"+scoringBean;
+				context.debugMsg(msg, MsgType.ScoreCard, isdebug);
+			}
 			ScoringStrategy scoringStrategy=(ScoringStrategy)context.getApplicationContext().getBean(scoringBean);
 			actualScore=scoringStrategy.calculate(card, context);
 		}

+ 11 - 3
urule-core/src/main/java/com/bstek/urule/model/scorecard/runtime/ScorecardImpl.java

@@ -19,6 +19,8 @@ import java.math.BigDecimal;
 import java.util.List;
 
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
+import com.bstek.urule.runtime.rete.Context;
 
 /**
  * @author Jacky.gao
@@ -26,23 +28,27 @@ import com.bstek.urule.Utils;
  */
 public class ScorecardImpl implements Scorecard {
 	private String name;
+	private boolean debug;
 	private List<RowItem> rowItems;
 	
-	public ScorecardImpl(String name, List<RowItem> rowItems) {
+	public ScorecardImpl(String name, List<RowItem> rowItems,boolean debug) {
 		this.name = name;
 		this.rowItems = rowItems;
+		this.debug=debug;
 	}
 
-	public BigDecimal executeSum(){
+	public BigDecimal executeSum(Context context){
 		BigDecimal result=new BigDecimal(0);
 		for(RowItem row:rowItems){
 			BigDecimal score=Utils.toBigDecimal(row.getScore());
 			row.setActualScore(score);
 			result=result.add(score);
 		}
+		String msg="+++求和得分:"+result;
+		context.debugMsg(msg, MsgType.ScoreCard, debug);
 		return result;
 	}
-	public BigDecimal executeWeightSum(){
+	public BigDecimal executeWeightSum(Context context){
 		BigDecimal result=new BigDecimal(0);
 		for(RowItem row:rowItems){
 			BigDecimal score=Utils.toBigDecimal(row.getScore());
@@ -51,6 +57,8 @@ public class ScorecardImpl implements Scorecard {
 			row.setActualScore(actualScore);
 			result=result.add(actualScore);
 		}
+		String msg="+++加权求和得分:"+result;
+		context.debugMsg(msg, MsgType.ScoreCard, debug);
 		return result;
 	}
 	@Override

+ 4 - 0
urule-core/src/main/java/com/bstek/urule/parse/scorecard/ScorecardParser.java

@@ -91,6 +91,10 @@ public class ScorecardParser implements Parser<ScorecardDefinition> {
 		if(StringUtils.isNotEmpty(enabled)){
 			card.setEnabled(Boolean.valueOf(enabled));
 		}
+		String debug=element.attributeValue("debug");
+		if(StringUtils.isNotEmpty(debug)){
+			card.setDebug(Boolean.valueOf(debug));
+		}
 		
 		card.setAttributeColWidth(element.attributeValue("attr-col-width"));
 		card.setAttributeColName(element.attributeValue("attr-col-name"));

+ 9 - 0
urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSession.java

@@ -15,6 +15,7 @@
  ******************************************************************************/
 package com.bstek.urule.runtime;
 
+import java.io.IOException;
 import java.util.Map;
 
 import com.bstek.urule.runtime.agenda.AgendaFilter;
@@ -93,4 +94,12 @@ public interface KnowledgeSession extends WorkingMemory{
 	 * @return 返回一个ExecutionResponse对象,其中包含规则流执行耗时信息
 	 */
 	FlowExecutionResponse startProcess(String processId,Map<String,Object> parameters);
+
+	/**
+	 * 执行将日志信息写入到日志文件操作,要看到日志文件我们需要设置urule.debugToFile属性值为true,<br>
+	 * 同时定义输出文件目录属性urule.defaultHtmlFileDebugPath,这样在urule.debug属性为true情况下就会向这个目录下写入日志文件,<br>
+	 * 需要的时候,可以通过实现com.bstek.urule.debug.DebugWriter接口定义自己的日志输出文件,这样就可以将日志输出到任何地方
+	 * @throws IOException
+	 */
+	void writeLogFile() throws IOException;
 }

+ 17 - 1
urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSessionFactory.java

@@ -14,6 +14,11 @@
  * the License.
  ******************************************************************************/
 package com.bstek.urule.runtime;
+
+import java.util.List;
+
+import com.bstek.urule.debug.MessageItem;
+
 /**
  * @author Jacky.gao
  * @since 2015年1月28日
@@ -28,13 +33,24 @@ public class KnowledgeSessionFactory {
 		return new KnowledgeSessionImpl(knowledgePackage);
 	}
 	
+	/**
+	 * 创建一个普通的KnowledgeSession对象,同时将上级调试信息集合传入,以便于后续调试输出
+	 * @param knowledgePackage 创建KnowledgeSession对象所需要的KnowledgePackage对象
+	 * @param debugMessageItems 上级调试信息集合
+	 * @return 返回一个新的KnowledgeSession对象
+	 */
+	public static KnowledgeSession newKnowledgeSession(KnowledgePackage knowledgePackage,List<MessageItem> debugMessageItems){
+		return new KnowledgeSessionImpl(knowledgePackage,debugMessageItems);
+	}	
+	
+	
 	/**
 	 * 创建一个普通的KnowledgeSession对象
 	 * @param knowledgePackages 创建KnowledgeSession对象所需要的KnowledgePackage集合对象
 	 * @return 返回一个新的KnowledgeSession对象
 	 */
 	public static KnowledgeSession newKnowledgeSession(KnowledgePackage[] knowledgePackages){
-		return new KnowledgeSessionImpl(knowledgePackages);
+		return new KnowledgeSessionImpl(knowledgePackages,null);
 	}
 	
 	/**

+ 25 - 5
urule-core/src/main/java/com/bstek/urule/runtime/KnowledgeSessionImpl.java

@@ -15,6 +15,7 @@
  ******************************************************************************/
 package com.bstek.urule.runtime;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -25,6 +26,8 @@ import java.util.Set;
 
 import com.bstek.urule.RuleException;
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.DebugWriter;
+import com.bstek.urule.debug.MessageItem;
 import com.bstek.urule.model.GeneralEntity;
 import com.bstek.urule.model.flow.FlowDefinition;
 import com.bstek.urule.model.flow.ins.FlowContextImpl;
@@ -70,6 +73,7 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 	private EvaluationContextImpl evaluationContext;
 	private FlowContextImpl flowContext;
 	private Agenda agenda;
+	private List<MessageItem> debugMessageItems=new ArrayList<MessageItem>();
 	private Map<String,Object> initParameters=new HashMap<String,Object>();
 	private List<Object> facts=new ArrayList<Object>();
 	private List<Object> historyFacts=new ArrayList<Object>();
@@ -79,9 +83,15 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 	private List<Map<?,?>> factMaps=new ArrayList<Map<?,?>>();
 	private List<KnowledgeEventListener> eventListeners=new ArrayList<KnowledgeEventListener>();
 	public KnowledgeSessionImpl(KnowledgePackage knowledgePackage) {
-		this(new KnowledgePackage[]{knowledgePackage});
+		this(new KnowledgePackage[]{knowledgePackage},null);
 	}
-	public KnowledgeSessionImpl(KnowledgePackage[] knowledgePackages){
+	public KnowledgeSessionImpl(KnowledgePackage knowledgePackage,List<MessageItem> debugMessageItems) {
+		this(new KnowledgePackage[]{knowledgePackage},debugMessageItems);
+	}
+	public KnowledgeSessionImpl(KnowledgePackage[] knowledgePackages,List<MessageItem> debugMessageItems){
+		if(debugMessageItems!=null){
+			this.debugMessageItems=debugMessageItems;			
+		}
 		for(KnowledgePackage knowledgePackage:knowledgePackages){
 			knowledgePackageList.add(knowledgePackage);
 			reteInstanceList.add(knowledgePackage.newReteInstance());
@@ -325,6 +335,16 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 			}			
 		}
 	}
+	@Override
+	public void writeLogFile() throws IOException{
+		if(debugMessageItems.size()==0){
+			return;
+		}
+		for(DebugWriter writer:Utils.getDebugWriters()){
+			writer.write(debugMessageItems);
+		}
+		debugMessageItems.clear();
+	}
 	
 	public List<Object> getAllFacts() {
 		return facts;
@@ -404,9 +424,9 @@ public class KnowledgeSessionImpl implements KnowledgeSession{
 				allVariableCateogoryMap.putAll(knowledgePackage.getVariableCateogoryMap());
 			}
 		}
-		context = new ContextImpl(this,Utils.getApplicationContext(),allVariableCateogoryMap);
-		evaluationContext=new EvaluationContextImpl(this,Utils.getApplicationContext(),allVariableCateogoryMap);
-		flowContext=new FlowContextImpl(this,allVariableCateogoryMap,Utils.getApplicationContext());
+		context = new ContextImpl(this,Utils.getApplicationContext(),allVariableCateogoryMap,debugMessageItems);
+		evaluationContext=new EvaluationContextImpl(this,Utils.getApplicationContext(),allVariableCateogoryMap,debugMessageItems);
+		flowContext=new FlowContextImpl(this,allVariableCateogoryMap,Utils.getApplicationContext(),debugMessageItems);
 	}
 	
 	public List<ReteInstance> getReteInstanceList() {

+ 6 - 0
urule-core/src/main/java/com/bstek/urule/runtime/rete/Context.java

@@ -15,8 +15,12 @@
  ******************************************************************************/
 package com.bstek.urule.runtime.rete;
 
+import java.util.List;
+
 import org.springframework.context.ApplicationContext;
 
+import com.bstek.urule.debug.MessageItem;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.runtime.WorkingMemory;
 import com.bstek.urule.runtime.assertor.AssertorEvaluator;
 
@@ -31,4 +35,6 @@ public interface Context {
 	String getVariableCategoryClass(String variableCategory);
 	WorkingMemory getWorkingMemory();
 	Object parseExpression(String expression);
+	List<MessageItem> getDebugMessageItems();
+	void debugMsg(String msg,MsgType type,boolean debug);
 }

+ 25 - 1
urule-core/src/main/java/com/bstek/urule/runtime/rete/ContextImpl.java

@@ -16,11 +16,15 @@
 package com.bstek.urule.runtime.rete;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.lang.StringUtils;
 import org.springframework.context.ApplicationContext;
 
+import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MessageItem;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.runtime.ElCalculator;
 import com.bstek.urule.runtime.WorkingMemory;
 import com.bstek.urule.runtime.assertor.AssertorEvaluator;
@@ -35,12 +39,14 @@ public class ContextImpl implements Context {
 	private Map<String,String> variableCategoryMap;
 	private ValueCompute valueCompute;
 	private WorkingMemory workingMemory;
+	private List<MessageItem> debugMessageItems;
 	private ElCalculator elCalculator=new ElCalculator();
-	public ContextImpl(WorkingMemory workingMemory,ApplicationContext applicationContext,Map<String,String> variableCategoryMap) {
+	public ContextImpl(WorkingMemory workingMemory,ApplicationContext applicationContext,Map<String,String> variableCategoryMap,List<MessageItem> debugMessageItems) {
 		this.workingMemory=workingMemory;
 		this.applicationContext = applicationContext;
 		this.assertorEvaluator=(AssertorEvaluator)applicationContext.getBean(AssertorEvaluator.BEAN_ID);
 		this.variableCategoryMap=variableCategoryMap;
+		this.debugMessageItems=debugMessageItems;
 		this.valueCompute=(ValueCompute)applicationContext.getBean(ValueCompute.BEAN_ID);
 	}
 	@Override
@@ -60,6 +66,24 @@ public class ContextImpl implements Context {
 		return elCalculator.eval(expression);
 	}
 	
+	@Override
+	public void debugMsg(String msg, MsgType type, boolean enableDebug) {
+		if(!Utils.isDebug() || !enableDebug){
+			return;
+		}
+		if(!Utils.isDebugToFile()){
+			System.out.println(msg);
+			return;
+		}
+		MessageItem item=new MessageItem(msg,type);
+		debugMessageItems.add(item);		
+	}
+	
+	@Override
+	public List<MessageItem> getDebugMessageItems() {
+		return debugMessageItems;
+	}
+	
 	public String getVariableCategoryClass(String variableCategory) {
 		String clazz=variableCategoryMap.get(variableCategory);
 		if(StringUtils.isEmpty(clazz)){

+ 4 - 3
urule-core/src/main/java/com/bstek/urule/runtime/rete/CriteriaActivity.java

@@ -20,6 +20,7 @@ import java.util.List;
 import java.util.Map;
 
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.rule.lhs.Criteria;
 import com.bstek.urule.model.rule.lhs.EvaluateResponse;
 
@@ -45,7 +46,7 @@ public class CriteriaActivity  extends AbstractActivity {
 		List<Object> allMatchedObjects=new ArrayList<Object>();
 		EvaluateResponse response=criteria.evaluate(context, obj,allMatchedObjects);
 		boolean result=response.getResult();
-		doDebug(response);
+		doDebug(response,context);
 		if(result){
 			context.setPrevActivity(this);
 			pass=true;
@@ -58,7 +59,7 @@ public class CriteriaActivity  extends AbstractActivity {
 		return null;
 	}
 	
-	private void doDebug(EvaluateResponse response){
+	private void doDebug(EvaluateResponse response,Context context){
 		if(!debug || !Utils.isDebug()){
 			return;
 		}
@@ -69,7 +70,7 @@ public class CriteriaActivity  extends AbstractActivity {
 		sb.append(" =>"+result);
 		sb.append(", 左值:"+(response.getLeftResult()==null ? "null" : response.getLeftResult()));
 		sb.append(", 右值:"+(response.getRightResult()==null ? "null" : response.getRightResult()));
-		System.out.println(sb.toString());
+		context.debugMsg(sb.toString(), MsgType.Condition, debug);
 	}
 	
 	@Override

+ 4 - 2
urule-core/src/main/java/com/bstek/urule/runtime/rete/EvaluationContextImpl.java

@@ -15,10 +15,12 @@
  ******************************************************************************/
 package com.bstek.urule.runtime.rete;
 
+import java.util.List;
 import java.util.Map;
 
 import org.springframework.context.ApplicationContext;
 
+import com.bstek.urule.debug.MessageItem;
 import com.bstek.urule.runtime.WorkingMemory;
 
 /**
@@ -29,8 +31,8 @@ public class EvaluationContextImpl extends ContextImpl implements EvaluationCont
 	private Activity prevActivity;
 	public EvaluationContextImpl(WorkingMemory workingMemory,
 			ApplicationContext applicationContext, 
-			Map<String, String> variableCategoryMap) {
-		super(workingMemory, applicationContext, variableCategoryMap);
+			Map<String, String> variableCategoryMap,List<MessageItem> debugMessageItems) {
+		super(workingMemory, applicationContext, variableCategoryMap,debugMessageItems);
 	}
 	@Override
 	public Activity getPrevActivity() {

+ 4 - 2
urule-core/src/main/java/com/bstek/urule/runtime/rete/NamedCriteriaActivity.java

@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.commons.lang.StringUtils;
 
 import com.bstek.urule.Utils;
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.rule.lhs.EvaluateResponse;
 import com.bstek.urule.model.rule.lhs.NamedCriteria;
 
@@ -47,7 +48,7 @@ public class NamedCriteriaActivity  extends AbstractActivity{
 		List<Object> allMatchedObjects=new ArrayList<Object>();
 		EvaluateResponse response=criteria.evaluate(context,obj,allMatchedObjects);
 		boolean result=response.getResult();
-		doDebug(response);
+		doDebug(response,context);
 		if(result){
 			if(StringUtils.isNotBlank(referenceName)){
 				variableMap.put(referenceName,obj);				
@@ -63,7 +64,7 @@ public class NamedCriteriaActivity  extends AbstractActivity{
 		return null;
 	}
 	
-	private void doDebug(EvaluateResponse response){
+	private void doDebug(EvaluateResponse response,Context context){
 		if(!debug || !Utils.isDebug()){
 			return;
 		}
@@ -73,6 +74,7 @@ public class NamedCriteriaActivity  extends AbstractActivity{
 		String result=response.getResult() ? "满足" : "不满足";
 		sb.append(" =>"+result);
 		System.out.println(sb.toString());
+		context.debugMsg(sb.toString(), MsgType.Condition, debug);
 	}
 	
 	@Override

+ 4 - 2
urule-core/src/main/java/com/bstek/urule/runtime/rete/TerminalActivity.java

@@ -20,6 +20,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import com.bstek.urule.debug.MsgType;
 import com.bstek.urule.model.rule.Rule;
 import com.bstek.urule.runtime.KnowledgeSession;
 import com.bstek.urule.runtime.agenda.ActivationImpl;
@@ -41,8 +42,9 @@ public class TerminalActivity extends AbstractActivity {
 		result.add(tracker);
 		KnowledgeSession session = (KnowledgeSession)context.getWorkingMemory();
 		session.fireEvent(new ActivationCreatedEventImpl(ac,session));
-		if(rule.getDebug()!=null && rule.getDebug()){
-			//out debug info
+		if(rule.getDebug()!=null){
+			String msg="√√√规则【"+rule.getName()+"】成功匹配";
+			context.debugMsg(msg, MsgType.RuleMatch, rule.getDebug());
 		}
 		return result;
 	}

+ 2 - 0
urule-core/src/main/resources/urule-core-context.properties

@@ -2,7 +2,9 @@ urule.resporityServerUrl=
 urule.dateFormat=
 urule.knowledgeUpdateCycle=0
 urule.tempStorePath=
+urule.defaultHtmlFileDebugPath=
 urule.debug=true
+urule.debugToFile=false
 
 urule.trimFunctionDisabled=false
 urule.stringLengthFunctionDisabled=false

+ 5 - 0
urule-core/src/main/resources/urule-core-context.xml

@@ -14,6 +14,10 @@
 		</property>
 	</bean>
 	
+	<bean id="urule.defaultHtmlFileDebugWriter" class="com.bstek.urule.debug.DefaultHtmlFileDebugWriter">
+		<property name="path" value="${urule.defaultHtmlFileDebugPath}"></property>
+	</bean>
+	
 	<bean id="urule.knowledgeBuilder" class="com.bstek.urule.builder.KnowledgeBuilder">
 		<property name="reteBuilder" ref="urule.reteBuilder"></property>
 		<property name="rulesRebuilder" ref="urule.rulesRebuilder"></property>
@@ -117,6 +121,7 @@
 
 	<bean id="urule.utils" class="com.bstek.urule.Utils">
 		<property name="debug" value="${urule.debug}"></property>
+		<property name="debugToFile" value="${urule.debugToFile}"></property>
 	</bean>
 	
 	<bean id="urule.flowResourceBuilder" class="com.bstek.urule.builder.resource.FlowResourceBuilder">

Vissa filer visades inte eftersom för många filer har ändrats