package com.fr.web.core;
import com.fr.base.ConfigManager;
import com.fr.base.Env;
import com.fr.base.FRContext;
import com.fr.base.TemplateUtils;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.stable.CodeUtils;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.ErrorHandler;
import com.fr.stable.fun.impl.AbstractErrorHandler;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* 默认的向页面输出报错信息的错误输出器
*/
public class DefaultErrorHandler extends AbstractErrorHandler {
/**
* 默认的构造函数
*/
public DefaultErrorHandler() {
}
/**
* 输出报表服务器在运行时出现的错误信息
*
* @param req HTTP请求
* @param res HTTP响应
* @param throwable 异常
*/
public void error(HttpServletRequest req, HttpServletResponse res, Throwable throwable) {
error(req, res, throwable.getMessage(), throwable);
}
/**
* 输出报表服务器在运行时出现的错误信息
*
* @param req HTTP请求
* @param res HTTP响应
* @param message 表示异常信息的字符串
*/
public void error(HttpServletRequest req, HttpServletResponse res, String message) {
error(req, res, message, null);
}
/**
* 输出报表服务器在运行时出现的错误信息
*
* @param req HTTP请求
* @param res HTTP响应
* @param message 表示异常信息的字符串
* @param throwable 异常
*/
public void error(HttpServletRequest req, HttpServletResponse res,
String message, Throwable throwable) {
if (WebUtils.getDevice(req).isMobile()) {
postErrorMessageWithJSONObject(req, res, message, throwable);
} else {
postErrorMessageOnPC(req, res, message, throwable);
}
}
private void postErrorMessageOnPC(HttpServletRequest req, HttpServletResponse res, String message, Throwable throwable) {
Map<String, Object> map = new HashMap<String, Object>();
if (message == null) {//保证message不能为null.
message = StringUtils.EMPTY;
}
map.put("message", CodeUtils.htmlEncode(CodeUtils.cjkEncode(message)));
map.put("duration", ProductConstants.HISTORY);
map.put("companyname", ProductConstants.COMPANY_NAME);
try {
if (req.getParameter("frload") != null) {
//说明是在loading.js访问时出现的问题,那么不能传html文件过去,应该传一个alert的东西过去
PrintWriter writer = WebUtils.createPrintWriter(res);
writer.println(new StringBuffer().append("alert(\"").append(message.replaceAll("\"", "\\\\\"")).append("\")"));
writer.flush();
writer.close();
return;
}
if (throwable != null) {
map.put("exception", createThrowableMessage(throwable, true));
}
//james:error页面的编码从FRContext中获取
map.put("charset", CodeUtils.htmlEncode(ConfigManager.getProviderInstance().getServerCharset()));
String errorTemplate = "/com/fr/web/core/errorIframe.html";
// 自定义出错页面
if (StringUtils.isNotEmpty(ConfigManager.getProviderInstance().getErrorTemplate())) {
try {
userDefineHandler(req, res, map);
} catch (Exception e) {
WebUtils.writeOutTemplate(errorTemplate, res, map);
FRContext.getLogger().error(e.getMessage());
}
} else {
WebUtils.writeOutTemplate(errorTemplate, res, map);
}
} catch (IOException ioe) {
FRContext.getLogger().errorWithServerLevel(ioe.getMessage(), ioe);
}
}
private void postErrorMessageWithJSONObject(HttpServletRequest req, HttpServletResponse res, String message, Throwable throwable) {
JSONObject errorJSON = new JSONObject();
PrintWriter writer = null;
try {
errorJSON.put("message", message);
errorJSON.put("exception", createThrowableMessage(throwable, false));
writer = WebUtils.createPrintWriter(res);
writer.println(errorJSON);
writer.flush();
writer.close();
} catch (Exception e) {
try {
errorJSON.put("exception", createThrowableMessage(e.getCause(), false));
} catch (JSONException e1) {
FRContext.getLogger().error(e.getMessage(), e);
}
} finally {
if (writer != null) {
writer.flush();
writer.close();
}
}
}
private String createThrowableMessage(Throwable throwable, boolean useCJK) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
throwable.printStackTrace(printWriter);
try {
return useCJK ? CodeUtils.htmlEncode(CodeUtils.cjkEncode(stringWriter.toString())) : stringWriter.toString();
} finally {
printWriter.flush();
printWriter.close();
}
}
private void userDefineHandler(HttpServletRequest req, HttpServletResponse res, Map map) throws Exception {
Env currentEnv = FRContext.getCurrentEnv();
if (currentEnv == null) {
throw new IllegalStateException("Env is null..");
}
String errorTemplate = ConfigManager.getProviderInstance().getErrorTemplate();
if (StringUtils.isNotEmpty(errorTemplate) && !errorTemplate.endsWith(".html")) {
if (errorTemplate.length() > 0 && errorTemplate.charAt(0) == '/') {
errorTemplate = req.getContextPath() + errorTemplate;
}
map.put("redirectURL", errorTemplate);
WebUtils.writeOutTemplate("/com/fr/web/core/errorPostRedirect.html", res, map);
} else {
String envPath = currentEnv.getPath();
File htmlFile = new File(StableUtils.pathJoin(new String[]{new File(envPath).getParent(), errorTemplate}));
PrintWriter printWriter = WebUtils.createPrintWriter(res);
TemplateUtils.dealWithTemplate(new FileInputStream(htmlFile), StableUtils.RESOURCE_ENCODER, printWriter, map);
printWriter.flush();
printWriter.close();
}
}
}