浏览代码

JFinal 1.4 Release :)

JamesZhan 12 年之前
父节点
当前提交
9139a7a923

+ 33 - 12
src/com/jfinal/config/Constants.java

@@ -23,6 +23,7 @@ import com.jfinal.kit.PathKit;
 import com.jfinal.kit.StringKit;
 import com.jfinal.log.ILoggerFactory;
 import com.jfinal.log.Logger;
+import com.jfinal.render.IErrorRenderFactory;
 import com.jfinal.render.IMainRenderFactory;
 import com.jfinal.render.RenderFactory;
 import com.jfinal.render.ViewType;
@@ -33,8 +34,6 @@ import com.jfinal.token.ITokenCache;
  */
 final public class Constants {
 	
-	private String error404View;
-	private String error500View;
 	private String fileRenderPath;
 	private String uploadedFileSaveDirectory;
 	
@@ -153,20 +152,12 @@ final public class Constants {
 		this.velocityViewExtension = velocityViewExtension.startsWith(".") ? velocityViewExtension : "." + velocityViewExtension;
 	}
 	
-	public String getError404View() {
-		return error404View;
-	}
-	
 	/**
 	 * Set error 404 view.
 	 * @param error404View the error 404 view
 	 */
 	public void setError404View(String error404View) {
-		this.error404View = error404View;
-	}
-	
-	public String getError500View() {
-		return error500View;
+		errorViewMapping.put(404, error404View);
 	}
 	
 	/**
@@ -174,7 +165,31 @@ final public class Constants {
 	 * @param error500View the error 500 view
 	 */
 	public void setError500View(String error500View) {
-		this.error500View = error500View;
+		errorViewMapping.put(500, error500View);
+	}
+	
+	/**
+	 * Set error 401 view.
+	 * @param error401View the error 401 view
+	 */
+	public void setError401View(String error401View) {
+		errorViewMapping.put(401, error401View);
+	}
+	
+	/**
+	 * Set error 403 view.
+	 * @param error403View the error 403 view
+	 */
+	public void setError403View(String error403View) {
+		errorViewMapping.put(403, error403View);
+	}
+	
+	private java.util.Map<Integer, String> errorViewMapping = new java.util.HashMap<Integer, String>();
+	public void setErrorView(int errorCode, String errorView) {
+		errorViewMapping.put(errorCode, errorView);
+	}
+	public String getErrorView(int errorCode) {
+		return errorViewMapping.get(errorCode);
 	}
 	
 	public String getFileRenderPath() {
@@ -294,6 +309,12 @@ final public class Constants {
 			throw new IllegalArgumentException("loggerFactory can not be null.");
 		Logger.setLoggerFactory(loggerFactory);
 	}
+	
+	public void setErrorRenderFactory(IErrorRenderFactory errorRenderFactory) {
+		if (errorRenderFactory == null)
+			throw new IllegalArgumentException("errorRenderFactory can not be null.");
+		RenderFactory.setErrorRenderFactory(errorRenderFactory);
+	}
 }
 
 

+ 57 - 0
src/com/jfinal/core/ActionException.java

@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2011-2012, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jfinal.core;
+
+import com.jfinal.kit.StringKit;
+import com.jfinal.render.Render;
+import com.jfinal.render.RenderFactory;
+
+/**
+ * ActionException.
+ */
+public class ActionException extends RuntimeException {
+	
+	private static final long serialVersionUID = 1998063243843477017L;
+	private int errorCode;
+	private Render errorRender;
+	
+	public ActionException(int errorCode, Render errorRender) {
+		if (errorRender == null)
+			throw new IllegalArgumentException("The parameter errorRender can not be null.");
+		
+		this.errorCode = errorCode;
+		this.errorRender = errorRender;
+	}
+	
+	public ActionException(int errorCode, String errorView) {
+		if (StringKit.isBlank(errorView))
+			throw new IllegalArgumentException("The parameter errorView can not be blank.");
+		
+		this.errorCode = errorCode;
+		this.errorRender = RenderFactory.me().getRender(errorView);
+	}
+	
+	public int getErrorCode() {
+		return errorCode;
+	}
+	
+	public Render getErrorRender() {
+		return errorRender;
+	}
+}
+
+

+ 30 - 15
src/com/jfinal/core/ActionHandler.java

@@ -21,8 +21,6 @@ import javax.servlet.http.HttpServletResponse;
 import com.jfinal.config.Constants;
 import com.jfinal.handler.Handler;
 import com.jfinal.log.Logger;
-import com.jfinal.render.Error404Exception;
-import com.jfinal.render.Error500Exception;
 import com.jfinal.render.Render;
 import com.jfinal.render.RenderException;
 import com.jfinal.render.RenderFactory;
@@ -62,7 +60,7 @@ final class ActionHandler extends Handler {
 				String qs = request.getQueryString();
 				log.warn("Action not found: " + (qs == null ? target : target + "?" + qs));
 			}
-			renderFactory.getError404Render().setContext(request, response).render();
+			renderFactory.getErrorRender(404).setContext(request, response).render();
 			return ;
 		}
 		
@@ -99,26 +97,43 @@ final class ActionHandler extends Handler {
 				log.error(qs == null ? target : target + "?" + qs, e);
 			}
 		}
-		catch (Error404Exception e) {
-			if (log.isWarnEnabled()) {
-				String qs = request.getQueryString();
-				log.warn("Resource not found: " + (qs == null ? target : target + "?" + qs));
+		catch (ActionException e) {
+			int errorCode = e.getErrorCode();
+			if (errorCode == 404) {
+				if (log.isWarnEnabled()) {
+					String qs = request.getQueryString();
+					log.warn("404 Not Found: " + (qs == null ? target : target + "?" + qs));
+				}
+				e.getErrorRender().setContext(request, response).render();
 			}
-			e.getError404Render().setContext(request, response).render();
-		}
-		catch (Error500Exception e) {
-			if (log.isErrorEnabled()) {
-				String qs = request.getQueryString();
-				log.error(qs == null ? target : target + "?" + qs, e);
+			else if (errorCode == 401) {
+				if (log.isWarnEnabled()) {
+					String qs = request.getQueryString();
+					log.warn("401 Unauthorized: " + (qs == null ? target : target + "?" + qs));
+				}
+				e.getErrorRender().setContext(request, response).render();
+			}
+			else if (errorCode == 403) {
+				if (log.isWarnEnabled()) {
+					String qs = request.getQueryString();
+					log.warn("403 Forbidden: " + (qs == null ? target : target + "?" + qs));
+				}
+				e.getErrorRender().setContext(request, response).render();
+			}
+			else {
+				if (log.isErrorEnabled()) {
+					String qs = request.getQueryString();
+					log.error(qs == null ? target : target + "?" + qs, e);
+				}
+				e.getErrorRender().setContext(request, response).render();
 			}
-			e.getError500Render().setContext(request, response).render();
 		}
 		catch (Exception e) {
 			if (log.isErrorEnabled()) {
 				String qs = request.getQueryString();
 				log.error(qs == null ? target : target + "?" + qs, e);
 			}
-			renderFactory.getError500Render().setContext(request, response).render();
+			renderFactory.getErrorRender(500).setContext(request, response).render();
 		}
 	}
 }

+ 1 - 0
src/com/jfinal/core/ActionMapping.java

@@ -56,6 +56,7 @@ final class ActionMapping {
 	}
 	
 	void buildActionMapping() {
+		mapping.clear();
 		Set<String> excludedMethodName = buildExcludedMethodName();
 		InterceptorBuilder interceptorBuilder = new InterceptorBuilder();
 		Interceptor[] defaultInters = interceptors.getInterceptorArray();

+ 1 - 1
src/com/jfinal/core/Const.java

@@ -24,7 +24,7 @@ import com.jfinal.render.ViewType;
  */
 public interface Const {
 	
-	String JFINAL_VERSION = "1.3";
+	String JFINAL_VERSION = "1.4";
 	
 	ViewType DEFAULT_VIEW_TYPE = ViewType.FREE_MARKER;
 	

+ 29 - 36
src/com/jfinal/core/Controller.java

@@ -203,12 +203,12 @@ public abstract class Controller {
 		return (Integer)request.getAttribute(name);
 	}
 	
-	private Integer getParaToInt_(String result, Integer defaultValue) {
-		if (result == null)
+	private Integer toInt(String value, Integer defaultValue) {
+		if (value == null)
 			return defaultValue;
-		if (result.startsWith("N") || result.startsWith("n"))
-			return -Integer.parseInt(result.substring(1));
-		return Integer.parseInt(result);
+		if (value.startsWith("N") || value.startsWith("n"))
+			return -Integer.parseInt(value.substring(1));
+		return Integer.parseInt(value);
 	}
 	
 	/**
@@ -217,7 +217,7 @@ public abstract class Controller {
 	 * @return a Integer representing the single value of the parameter
 	 */
 	public Integer getParaToInt(String name) {
-		return getParaToInt_(request.getParameter(name), null);
+		return toInt(request.getParameter(name), null);
 	}
 	
 	/**
@@ -226,15 +226,15 @@ public abstract class Controller {
 	 * @return a Integer representing the single value of the parameter
 	 */
 	public Integer getParaToInt(String name, Integer defaultValue) {
-		return getParaToInt_(request.getParameter(name), defaultValue);
+		return toInt(request.getParameter(name), defaultValue);
 	}
 	
-	private Long getParaToLong_(String result, Long defaultValue) {
-		if (result == null)
+	private Long toLong(String value, Long defaultValue) {
+		if (value == null)
 			return defaultValue;
-		if (result.startsWith("N") || result.startsWith("n"))
-			return -Long.parseLong(result.substring(1));
-		return Long.parseLong(result);
+		if (value.startsWith("N") || value.startsWith("n"))
+			return -Long.parseLong(value.substring(1));
+		return Long.parseLong(value);
 	}
 	
 	/**
@@ -243,7 +243,7 @@ public abstract class Controller {
 	 * @return a Integer representing the single value of the parameter
 	 */
 	public Long getParaToLong(String name) {
-		return getParaToLong_(request.getParameter(name), null);
+		return toLong(request.getParameter(name), null);
 	}
 	
 	/**
@@ -252,7 +252,7 @@ public abstract class Controller {
 	 * @return a Integer representing the single value of the parameter
 	 */
 	public Long getParaToLong(String name, Long defaultValue) {
-		return getParaToLong_(request.getParameter(name), defaultValue);
+		return toLong(request.getParameter(name), defaultValue);
 	}
 	
 	/**
@@ -522,42 +522,42 @@ public abstract class Controller {
 	 * Get para from url and conver to Integer. The first index is 0
 	 */
 	public Integer getParaToInt(int index) {
-		return getParaToInt_(getPara(index), null);
+		return toInt(getPara(index), null);
 	}
 	
 	/**
 	 * Get para from url and conver to Integer with default value if it is null.
 	 */
 	public Integer getParaToInt(int index, Integer defaultValue) {
-		return getParaToInt_(getPara(index), defaultValue);
+		return toInt(getPara(index), defaultValue);
 	}
 	
 	/**
 	 * Get para from url and conver to Long.
 	 */
 	public Long getParaToLong(int index) {
-		return getParaToLong_(getPara(index), null);
+		return toLong(getPara(index), null);
 	}
 	
 	/**
 	 * Get para from url and conver to Long with default value if it is null.
 	 */
 	public Long getParaToLong(int index, Long defaultValue) {
-		return getParaToLong_(getPara(index), defaultValue);
+		return toLong(getPara(index), defaultValue);
 	}
 	
 	/**
 	 * Get all para from url and convert to Integer
 	 */
 	public Integer getParaToInt() {
-		return getParaToInt_(getPara(), null);
+		return toInt(getPara(), null);
 	}
 	
 	/**
 	 * Get all para from url and convert to Long
 	 */
 	public Long getParaToLong() {
-		return getParaToLong_(getPara(), null);
+		return toLong(getPara(), null);
 	}
 	
 	/**
@@ -975,31 +975,24 @@ public abstract class Controller {
 	}
 	
 	/**
-	 * Render with view and 404 status
+	 * Render with view and errorCode status
 	 */
-	public void renderError404(String view) {
-		throw new com.jfinal.render.Error404Exception(renderFactory.getError404Render(view));
+	public void renderError(int errorCode, String view) {
+		throw new ActionException(errorCode, renderFactory.getErrorRender(errorCode, view));
 	}
 	
 	/**
-	 * Render with view and 404 status configured in JFinalConfig
+	 * Render with render and errorCode status
 	 */
-	public void renderError404() {
-		throw new com.jfinal.render.Error404Exception(renderFactory.getError404Render());
+	public void renderError(int errorCode, Render render) {
+		throw new ActionException(errorCode, render);
 	}
 	
 	/**
-	 * Render with view and 500 status
+	 * Render with view and errorCode status configured in JFinalConfig
 	 */
-	public void renderError500(String view) {
-		throw new com.jfinal.render.Error500Exception(renderFactory.getError500Render(view));
-	}
-	
-	/**
-	 * Render with view and 500 status configured in JFinalConfig
-	 */
-	public void renderError500() {
-		throw new com.jfinal.render.Error500Exception(renderFactory.getError500Render());
+	public void renderError(int errorCode) {
+		throw new ActionException(errorCode, renderFactory.getErrorRender(errorCode));
 	}
 	
 	/**

+ 1 - 1
src/com/jfinal/ext/interceptor/GET.java

@@ -13,6 +13,6 @@ public class GET implements Interceptor {
 		if ("GET".equalsIgnoreCase(controller.getRequest().getMethod()))
 			ai.invoke();
 		else
-			controller.renderError404();
+			controller.renderError(404);
 	}
 }

+ 1 - 1
src/com/jfinal/ext/interceptor/NoUrlPara.java

@@ -29,6 +29,6 @@ public class NoUrlPara implements Interceptor {
 		if (controller.getPara() == null)
 			invocation.invoke();
 		else
-			controller.renderError404();
+			controller.renderError(404);
 	}
 }

+ 1 - 1
src/com/jfinal/ext/interceptor/POST.java

@@ -13,6 +13,6 @@ public class POST implements Interceptor {
 		if ("POST".equalsIgnoreCase(controller.getRequest().getMethod().toUpperCase()))
 			ai.invoke();
 		else
-			controller.renderError404();
+			controller.renderError(404);
 	}
 }

+ 1 - 1
src/com/jfinal/ext/interceptor/Restful.java

@@ -53,7 +53,7 @@ public class Restful implements Interceptor {
 		Boolean isRestfulForward = controller.getAttr(isRestfulForwardKey);
 		String methodName = ai.getMethodName();
 		if (set.contains(methodName) && isRestfulForward== null) {
-			ai.getController().renderError404();
+			ai.getController().renderError(404);
 			return ;
 		}
 		

+ 19 - 14
src/com/jfinal/render/Error500Exception.java

@@ -14,21 +14,26 @@
  * limitations under the License.
  */
 
-package com.jfinal.render;
+package com.jfinal.kit;
+
+import java.io.File;
 
 /**
- * Error500Exception.
+ * FileKit.
  */
-public class Error500Exception extends RuntimeException {
-	
-	private static final long serialVersionUID = -7521710800649772411L;
-	private Render error500Render;
-	
-	public Error500Exception(Render error500Render) {
-		this.error500Render = error500Render;
-	}
-	
-	public Render getError500Render() {
-		return error500Render;
+public class FileKit {
+	public static void delete(File file) {
+		if (file != null && file.exists()) {
+			if (file.isFile()) {
+				file.delete();
+			}
+			else if (file.isDirectory()) {
+				File files[] = file.listFiles();
+				for (int i=0; i<files.length; i++) {
+					delete(files[i]);
+				}
+			}
+			file.delete();
+		}
 	}
-}
+}

+ 12 - 2
src/com/jfinal/kit/JsonKit.java

@@ -39,7 +39,13 @@ import com.jfinal.plugin.activerecord.Record;
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class JsonKit {
 	
-	private static final int DEFAULT_DEPTH = 8;
+	private static int convertDepth = 8;
+	
+	public static void setConvertDepth(int convertDepth) {
+		if (convertDepth < 2)
+			throw new IllegalArgumentException("convert depth can not less than 2.");
+		JsonKit.convertDepth = convertDepth;
+	}
 	
 	public static String mapToJson(Map map, int depth) {
 		if(map == null)
@@ -158,7 +164,7 @@ public class JsonKit {
 	}
 	
 	public static String toJson(Object value) {
-		return toJson(value, DEFAULT_DEPTH);
+		return toJson(value, convertDepth);
 	}
 	
 	public static String toJson(Object value, int depth) {
@@ -224,6 +230,10 @@ public class JsonKit {
 				list.add(arr[i]);
 			return listToJson(list, depth);
 		}
+		if (value instanceof Enum) {
+			return "\"" + ((Enum)value).name() + "\"";
+		}
+		
 		return beanToJson(value, depth);
 	}
 	

+ 23 - 3
src/com/jfinal/kit/PathKit.java

@@ -17,7 +17,6 @@
 package com.jfinal.kit;
 
 import java.io.File;
-import java.io.IOException;
 
 /**
  * new File("..\path\abc.txt") 中的三个方法获取路径的方法
@@ -28,6 +27,7 @@ import java.io.IOException;
 public class PathKit {
 	
 	private static String webRootPath;
+	private static String rootClassPath;
 	
 	@SuppressWarnings("rawtypes")
 	public static String getPath(Class clazz) {
@@ -41,8 +41,17 @@ public class PathKit {
 	}
 	
 	public static String getRootClassPath() {
-		String path = PathKit.class.getClassLoader().getResource("").getPath();
-		return new File(path).getAbsolutePath();
+		if (rootClassPath == null) {
+			try {
+				String path = PathKit.class.getClassLoader().getResource("").toURI().getPath();
+				rootClassPath = new File(path).getAbsolutePath();
+			}
+			catch (Exception e) {
+				String path = PathKit.class.getClassLoader().getResource("").getPath();
+				rootClassPath = new File(path).getAbsolutePath();
+			}
+		}
+		return rootClassPath;
 	}
 	
 	public static String getPackagePath(Object object) {
@@ -71,12 +80,23 @@ public class PathKit {
 	
 	private static String detectWebRootPath() {
 		try {
+			String path = PathKit.class.getResource("/").toURI().getPath();
+			return new File(path).getParentFile().getParentFile().getCanonicalPath();
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+	
+	/*
+	private static String detectWebRootPath() {
+		try {
 			String path = PathKit.class.getResource("/").getFile();
 			return new File(path).getParentFile().getParentFile().getCanonicalPath();
 		} catch (IOException e) {
 			throw new RuntimeException(e);
 		}
 	}
+	*/
 }
 
 

+ 15 - 4
src/com/jfinal/plugin/activerecord/Db.java

@@ -763,10 +763,21 @@ public class Db {
 	 * @return true if transaction executing succeed otherwise false
 	 */
 	public  static boolean tx(int transactionLevel, IAtom atom) {
-		if (DbKit.isExistsThreadLocalConnection())
-			throw new ActiveRecordException("Nested transaction can not be supported. You can't execute transaction inside another transaction.");
+		Connection conn = DbKit.getThreadLocalConnection();
+		if (conn != null) {	// Nested transaction support
+			try {
+				if (conn.getTransactionIsolation() < transactionLevel)
+					conn.setTransactionIsolation(transactionLevel);
+				boolean result = atom.run();
+				if (result)
+					return true;
+				throw new ActiveRecordException("Nested transaction is failure.");	// important:can not return false
+			}
+			catch (SQLException e) {
+				throw new ActiveRecordException(e);
+			}
+		}
 		
-		Connection conn = null;
 		Boolean autoCommit = null;
 		try {
 			conn = DbKit.getDataSource().getConnection();
@@ -783,7 +794,7 @@ public class Db {
 		} catch (Exception e) {
 			if (conn != null)
 				try {conn.rollback();} catch (Exception e1) {e1.printStackTrace();}
-			throw new ActiveRecordException(e);
+			return false;	// throw new ActiveRecordException(e);
 		} finally {
 			try {
 				if (conn != null) {

+ 3 - 3
src/com/jfinal/plugin/activerecord/DbKit.java

@@ -139,11 +139,11 @@ public final class DbKit {
 	}*/
 	
 	/**
-	 * Helps to prevent nested transaction.
+	 * Helps to implement nested transaction.
 	 * Tx.intercept(...) and Db.tx(...) need this method to detected if it in nested transaction.
 	 */
-	public static final boolean isExistsThreadLocalConnection() {
-		return threadLocal.get() != null;
+	public static final Connection getThreadLocalConnection() {
+		return threadLocal.get();
 	}
 	
 	/**

+ 2 - 2
src/com/jfinal/plugin/activerecord/Model.java

@@ -495,7 +495,7 @@ public abstract class Model<M extends Model> implements Serializable {
 	
 	/**
 	 * Set attributes with Map.
-	 * @param attrs Attributes of this model
+	 * @param attrs attributes of this model
 	 * @return this Model
 	 */
 	public M setAttrs(Map<String, Object> attrs) {
@@ -572,7 +572,7 @@ public abstract class Model<M extends Model> implements Serializable {
 	
 	/**
 	 * Keep attribute of this model and remove other attributes.
-	 * @param attr the attribute names of the model
+	 * @param attr the attribute name of the model
 	 * @return this model
 	 */
 	public M keep(String attr) {

+ 2 - 2
src/com/jfinal/plugin/activerecord/OneConnectionPerThread.java

@@ -21,8 +21,8 @@ import com.jfinal.aop.Interceptor;
 import com.jfinal.core.ActionInvocation;
 
 /**
- * 实现一个线程仅一个数据库连接, 以提高性能
- * 注意是否与事务冲突了
+ * One Connection Per Thread for one request.<br>
+ * warning: can not use this interceptor with transaction feature like Tx, Db.tx(...)
  */
 public class OneConnectionPerThread implements Interceptor {
 	

+ 12 - 3
src/com/jfinal/plugin/activerecord/tx/Tx.java

@@ -17,6 +17,7 @@
 package com.jfinal.plugin.activerecord.tx;
 
 import java.sql.Connection;
+import java.sql.SQLException;
 import com.jfinal.aop.Interceptor;
 import com.jfinal.core.ActionInvocation;
 import com.jfinal.plugin.activerecord.ActiveRecordException;
@@ -33,10 +34,18 @@ public class Tx implements Interceptor {
 	}
 	
 	public void intercept(ActionInvocation invocation) {
-		if (DbKit.isExistsThreadLocalConnection())
-			throw new ActiveRecordException("Nested transaction can not be supported. You can't execute transaction inside another transaction.");
+		Connection conn = DbKit.getThreadLocalConnection();
+		if (conn != null) {	// Nested transaction support
+			try {
+				if (conn.getTransactionIsolation() < getTransactionLevel())
+					conn.setTransactionIsolation(getTransactionLevel());
+				invocation.invoke();
+				return ;
+			} catch (SQLException e) {
+				throw new ActiveRecordException(e);
+			}
+		}
 		
-		Connection conn = null;
 		Boolean autoCommit = null;
 		try {
 			conn = DbKit.getConnection();

+ 4 - 4
src/com/jfinal/plugin/ehcache/CacheInterceptor.java

@@ -106,16 +106,16 @@ public class CacheInterceptor implements Interceptor {
 		CacheKit.put(cacheName, cacheKey, cacheData);
 	}
 	
-	private void useCacheDataAndRender(Map<String, Object> data, Controller controller) {
+	private void useCacheDataAndRender(Map<String, Object> cacheData, Controller controller) {
 		HttpServletRequest request = controller.getRequest();
-		Set<Entry<String, Object>> set = data.entrySet();
+		Set<Entry<String, Object>> set = cacheData.entrySet();
 		for (Iterator<Entry<String, Object>> it=set.iterator(); it.hasNext();) {
 			Entry<String, Object> entry = it.next();
 			request.setAttribute(entry.getKey(), entry.getValue());
 		}
-		
-		controller.render((Render)request.getAttribute(renderKey));		// set render from cache
 		request.removeAttribute(renderKey);
+		
+		controller.render((Render)cacheData.get(renderKey));		// set render from cacheData
 	}
 }
 

+ 0 - 69
src/com/jfinal/render/Error404Render.java

@@ -1,69 +0,0 @@
-/**
- * Copyright (c) 2011-2012, James Zhan 詹波 (jfinal@126.com).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.jfinal.render;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.http.HttpServletResponse;
-import com.jfinal.core.Const;
-
-/**
- * Error404Render.
- */
-public class Error404Render extends Render {
-	
-	private static final long serialVersionUID = 3925763221184467994L;
-	private static final String contentType = "text/html;charset=" + getEncoding();
-	private static final String defaultHtml = "<html><head><title>404 Not Found</title></head><body bgcolor='white'><center><h1>404 Not Found</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
-	
-	public Error404Render(String view) {
-		this.view = view;
-	}
-	
-	public Error404Render() {
-		
-	}
-	
-	public void render() {
-		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-		
-		// render with view
-		if (view != null) {
-			RenderFactory.me().getRender(view).setContext(request, response).render();
-			return;
-		}
-		
-		// render with defaultHtml
-		PrintWriter writer = null;
-		try {
-			response.setContentType(contentType);
-	        writer = response.getWriter();
-	        writer.write(defaultHtml);
-	        writer.flush();
-		} catch (IOException e) {
-			throw new RenderException(e);
-		}
-		finally {
-			if (writer != null)
-				writer.close();
-		}
-	}
-}
-
-
-
-

+ 0 - 70
src/com/jfinal/render/Error500Render.java

@@ -1,70 +0,0 @@
-/**
- * Copyright (c) 2011-2012, James Zhan 詹波 (jfinal@126.com).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.jfinal.render;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.http.HttpServletResponse;
-import com.jfinal.core.Const;
-
-/**
- * Error500Render.
- */
-public class Error500Render extends Render {
-	
-	private static final long serialVersionUID = -7993459890626145958L;
-	private static final String contentType = "text/html;charset=" + getEncoding();
-	private static final String defaultHtml = "<html><head><title>500 Internal Server Error</title></head><body bgcolor='white'><center><h1>500 Internal Server Error</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
-	
-	public Error500Render(String view) {
-		this.view = view;
-	}
-	
-	public Error500Render() {
-		
-	}
-	
-	public void render() {
-		response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-		
-		// render with view
-		if (view != null) {
-			RenderFactory.me().getRender(view).setContext(request, response).render();
-			return;
-		}
-		
-		// render with defaultHtml
-		PrintWriter writer = null;
-		try {
-			response.setContentType(contentType);
-	        writer = response.getWriter();
-	        writer.write(defaultHtml);
-	        writer.flush();
-		} catch (IOException e) {
-			throw new RenderException(e);
-		}
-		finally {
-			if (writer != null)
-				writer.close();
-		}
-	}
-}
-
-
-
-
-

+ 92 - 0
src/com/jfinal/render/ErrorRender.java

@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) 2011-2012, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jfinal.render;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import com.jfinal.core.Const;
+
+/**
+ * ErrorRender.
+ */
+public class ErrorRender extends Render {
+	
+	private static final long serialVersionUID = -7175292712918557096L;
+	protected static final String contentType = "text/html;charset=" + getEncoding();
+	
+	protected static final String html404 = "<html><head><title>404 Not Found</title></head><body bgcolor='white'><center><h1>404 Not Found</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
+	protected static final String html500 = "<html><head><title>500 Internal Server Error</title></head><body bgcolor='white'><center><h1>500 Internal Server Error</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
+	
+	protected static final String html401 = "<html><head><title>401 Unauthorized</title></head><body bgcolor='white'><center><h1>401 Unauthorized</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
+	protected static final String html403 = "<html><head><title>403 Forbidden</title></head><body bgcolor='white'><center><h1>403 Forbidden</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
+	
+	protected int errorCode;
+	
+	public ErrorRender(int errorCode, String view) {
+		this.errorCode = errorCode;
+		this.view = view;
+	}
+	
+	public void render() {
+		response.setStatus(getErrorCode());	// HttpServletResponse.SC_XXX_XXX
+		
+		// render with view
+		String view = getView();
+		if (view != null) {
+			RenderFactory.me().getRender(view).setContext(request, response).render();
+			return;
+		}
+		
+		// render with html content
+		PrintWriter writer = null;
+		try {
+			response.setContentType(contentType);
+	        writer = response.getWriter();
+	        writer.write(getErrorHtml());
+	        writer.flush();
+		} catch (IOException e) {
+			throw new RenderException(e);
+		}
+		finally {
+			if (writer != null)
+				writer.close();
+		}
+	}
+	
+	public String getErrorHtml() {
+		int errorCode = getErrorCode();
+		if (errorCode == 404)
+			return html404;
+		else if (errorCode == 500)
+			return html500;
+		else if (errorCode == 401)
+			return html401;
+		else if (errorCode == 403)
+			return html403;
+		else
+			return "<html><head><title>" + errorCode + " Error</title></head><body bgcolor='white'><center><h1>" + errorCode + " Error</h1></center><hr><center><a href='http://www.jfinal.com'>JFinal/" + Const.JFINAL_VERSION + "</a></center></body></html>";
+	}
+	
+	public int getErrorCode() {
+		return errorCode;
+	}
+}
+
+
+
+
+

+ 1 - 1
src/com/jfinal/render/FileRender.java

@@ -66,7 +66,7 @@ public class FileRender extends Render {
             // return;
 			
 			// throw new RenderException("File not found!");
-			RenderFactory.me().getError404Render().setContext(request, response).render();
+			RenderFactory.me().getErrorRender(404).setContext(request, response).render();
 			return ;
         }
 		

+ 4 - 14
src/com/jfinal/render/Error404Exception.java

@@ -17,18 +17,8 @@
 package com.jfinal.render;
 
 /**
- * Error404Exception.
+ * IErrorRenderFactory.
  */
-public class Error404Exception extends RuntimeException {
-	
-	private static final long serialVersionUID = 7620194943724436754L;
-	private Render error404Render;
-	
-	public Error404Exception(Render error404Render) {
-		this.error404Render = error404Render;
-	}
-	
-	public Render getError404Render() {
-		return error404Render;
-	}
-}
+public interface IErrorRenderFactory {
+	public Render getRender(int errorCode, String view);
+}

+ 10 - 5
src/com/jfinal/render/JsonRender.java

@@ -45,6 +45,7 @@ public class JsonRender extends Render {
 	private static final String contentType = "application/json;charset=" + getEncoding();
 	private static final String contentTypeForIE = "text/html;charset=" + getEncoding();
 	private boolean forIE = false;
+	private static int convertDepth = 8;
 	
 	public JsonRender forIE() {
 		forIE = true;
@@ -62,7 +63,7 @@ public class JsonRender extends Render {
 	public JsonRender(final String key, final Object value) {
 		if (key == null)
 			throw new IllegalArgumentException("The parameter key can not be null.");
-		this.jsonText = JsonKit.mapToJson(new HashMap<String, Object>(){{put(key, value);}}, depth);
+		this.jsonText = JsonKit.mapToJson(new HashMap<String, Object>(){{put(key, value);}}, convertDepth);
 	}
 	
 	public JsonRender(String[] attrs) {
@@ -80,7 +81,13 @@ public class JsonRender extends Render {
 	public JsonRender(Object object) {
 		if (object == null)
 			throw new IllegalArgumentException("The parameter object can not be null.");
-		this.jsonText = JsonKit.toJson(object, depth);
+		this.jsonText = JsonKit.toJson(object, convertDepth);
+	}
+	
+	public static void setConvertDepth(int convertDepth) {
+		if (convertDepth < 2)
+			throw new IllegalArgumentException("convert depth can not less than 2.");
+		JsonRender.convertDepth = convertDepth;
 	}
 	
 	public void render() {
@@ -106,8 +113,6 @@ public class JsonRender extends Render {
 		}
 	}
 	
-	private static final int depth = 8;
-	
 	@SuppressWarnings({"rawtypes", "unchecked"})
 	private void buildJsonText() {
 		Map map = new HashMap();
@@ -124,7 +129,7 @@ public class JsonRender extends Render {
 			}
 		}
 		
-		this.jsonText = JsonKit.mapToJson(map, depth);
+		this.jsonText = JsonKit.mapToJson(map, convertDepth);
 	}
 }
 

+ 9 - 1
src/com/jfinal/render/Render.java

@@ -26,7 +26,7 @@ import com.jfinal.core.Const;
  */
 public abstract class Render implements Serializable {
 	
-	private static final long serialVersionUID = -6161983268638909080L;
+	private static final long serialVersionUID = 4055676662365675029L;
 	protected String view;
 	protected transient HttpServletRequest request;
 	protected transient HttpServletResponse response;
@@ -61,6 +61,14 @@ public abstract class Render implements Serializable {
 		return this;
 	}
 	
+	public String getView() {
+		return view;
+	}
+	
+	public void setView(String view) {
+		this.view = view;
+	}
+	
 	/**
 	 * Render to client
 	 */

+ 21 - 14
src/com/jfinal/render/RenderFactory.java

@@ -30,6 +30,7 @@ public class RenderFactory {
 	
 	private Constants constants;
 	private static IMainRenderFactory mainRenderFactory;
+	private static IErrorRenderFactory errorRenderFactory;
 	private static ServletContext servletContext;
 	
 	static ServletContext getServletContext() {
@@ -51,6 +52,11 @@ public class RenderFactory {
 			RenderFactory.mainRenderFactory = mainRenderFactory;
 	}
 	
+	public static void setErrorRenderFactory(IErrorRenderFactory errorRenderFactory) {
+		if (errorRenderFactory != null)
+			RenderFactory.errorRenderFactory = errorRenderFactory;
+	}
+	
 	public void init(Constants constants, ServletContext servletContext) {
 		this.constants = constants;
 		RenderFactory.servletContext = servletContext;
@@ -73,6 +79,11 @@ public class RenderFactory {
 			else
 				throw new RuntimeException("View Type can not be null.");
 		}
+		
+		// create errorRenderFactory
+		if (errorRenderFactory == null) {
+			errorRenderFactory = new ErrorRenderFactory();
+		}
 	}
 	
 	private void initFreeMarkerRender(ServletContext servletContext) {
@@ -172,22 +183,12 @@ public class RenderFactory {
 		}
 	}
 	
-	public Render getError404Render() {
-		String error404View = constants.getError404View();
-		return error404View != null ? new Error404Render(error404View) : new Error404Render();
-	}
-	
-	public Render getError404Render(String view) {
-		return new Error404Render(view);
+	public Render getErrorRender(int errorCode, String view) {
+		return errorRenderFactory.getRender(errorCode, view);
 	}
 	
-	public Render getError500Render() {
-		String error500View = constants.getError500View();
-		return error500View != null ? new Error500Render(error500View) : new Error500Render();
-	}
-	
-	public Render getError500Render(String view) {
-		return new Error500Render(view);
+	public Render getErrorRender(int errorCode) {
+		return errorRenderFactory.getRender(errorCode, constants.getErrorView(errorCode));
 	}
 	
 	public Render getFileRender(String fileName) {
@@ -253,6 +254,12 @@ public class RenderFactory {
 			return ".html";
 		}
 	}
+	
+	private static final class ErrorRenderFactory implements IErrorRenderFactory {
+		public Render getRender(int errorCode, String view) {
+			return new ErrorRender(errorCode, view);
+		}
+	}
 }
 
 

+ 17 - 1
src/com/jfinal/server/JettyServer.java

@@ -27,6 +27,7 @@ import org.eclipse.jetty.server.session.HashSessionManager;
 import org.eclipse.jetty.server.session.SessionHandler;
 import org.eclipse.jetty.webapp.WebAppContext;
 import com.jfinal.core.Const;
+import com.jfinal.kit.FileKit;
 import com.jfinal.kit.PathKit;
 import com.jfinal.kit.StringKit;
 
@@ -76,6 +77,8 @@ class JettyServer implements IServer {
 		if (!available(port))
 			throw new IllegalStateException("port: " + port + " already in use!");
 		
+		deleteSessionData();
+		
 		System.out.println("Starting JFinal " + Const.JFINAL_VERSION);
 		server = new Server();
 		SelectChannelConnector connector = new SelectChannelConnector();
@@ -121,10 +124,23 @@ class JettyServer implements IServer {
 		return;
 	}
 	
-	private void persistSession(WebAppContext webApp) {
+	private void deleteSessionData() {
+		try {
+			FileKit.delete(new File(getStoreDir()));
+		}
+		catch (Exception e) {
+		}
+	}
+	
+	private String getStoreDir() {
 		String storeDir = PathKit.getWebRootPath() + "/../../session_data" + context;
 		if ("\\".equals(File.separator))
 			storeDir = storeDir.replaceAll("/", "\\\\");
+		return storeDir;
+	}
+	
+	private void persistSession(WebAppContext webApp) {
+		String storeDir = getStoreDir();
 		
 		SessionManager sm = webApp.getSessionHandler().getSessionManager();
 		if (sm instanceof HashSessionManager) {