package cn.jcenterhome.service;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import cn.jcenterhome.util.BeanFactory;
import cn.jcenterhome.util.Common;
import cn.jcenterhome.util.FileHelper;
import cn.jcenterhome.util.JavaCenterHome;
import cn.jcenterhome.util.Md5Util;
import cn.jcenterhome.util.Serializer;
public class BlockService {
private DataBaseService dataBaseService = (DataBaseService) BeanFactory.getBean("dataBaseService");
@SuppressWarnings("unchecked")
public void block_batch(HttpServletRequest request,String param) {
Map<String, Object> SBLOCK = new HashMap<String, Object>();
Map<String, Object> sGlobal = (Map<String, Object>) request.getAttribute("sGlobal");
Map<String, Object> sConfig = (Map<String, Object>) request.getAttribute("sConfig");
String cachekey = smd5(param);
Map<String,Object> paramarr = parseparameter(param);
if(Common.empty(sConfig.get("allowcache"))) {
paramarr.put("cachetime", 0);
} else {
paramarr.put("cachetime", Common.intval((String)paramarr.get("cachetime")));
}
if(!Common.empty(paramarr.get("perpage"))) {
String pages = request.getParameter("page");
int page = Common.empty(pages)?1:Common.intval(pages);
if(page<1) page = 1;
if(page>1&&(Integer)paramarr.get("cachetime")>0){
cachekey = smd5(param+page);
}
}
Map caches = new HashMap();
if((Integer)paramarr.get("cachetime")>0) {
caches = block_get(cachekey,sGlobal,sConfig);
}
if(!Common.empty(caches.get("mtime")) && (Integer)sGlobal.get("timestamp")-(Integer)caches.get("mtime") <= (Integer)paramarr.get("cachetime")) {
SBLOCK.put((String) paramarr.get("cachename"), caches.get("values"));
SBLOCK.put(paramarr.get("cachename")+"_multipage",caches.get("multi"));
} else {
List<Map<String, Object>> blockarr = new ArrayList<Map<String, Object>>();
Map<String, Object> results = getparamsql(request,paramarr,sGlobal,sConfig);
if((Integer)results.get("count")>0) {
List<Map<String,Object>> values = dataBaseService.executeQuery((String)results.get("sql"));
blockarr = values;
}
SBLOCK.put((String) paramarr.get("cachename"), blockarr);
SBLOCK.put(paramarr.get("cachename")+"_multipage", results.get("multi"));
if((Integer)paramarr.get("cachetime")>0) {
Map<String,Object> multiMap = new HashMap<String,Object>();
multiMap.put("multipage", results.get("multi"));
blockarr.add(multiMap);
block_set(cachekey, blockarr,sGlobal,sConfig);
}
}
request.setAttribute("sBlock", SBLOCK);
}
private String smd5(String str) {
return Md5Util.encode(str).substring(8, 16);
}
private Map<String,Object> parseparameter(String param) {
Map<String,Object> paramarr = new HashMap<String,Object>();
String[]sarr = param.split("/");
if(Common.empty(sarr)) return paramarr;
int length = sarr.length;
for(int i=0; i<length; i=i+2) {
if((i+1)<length&&!Common.empty(sarr[i+1])) paramarr.put(sarr[i], Common.urlDecode(sarr[i+1]).replace("/", "").replace("\\", ""));
}
return paramarr;
}
@SuppressWarnings("unchecked")
private Map<String,Object> getparamsql(HttpServletRequest request,Map<String,Object> paramarr,Map<String, Object> sGlobal,Map<String, Object> sConfig) {
String sql = (String) paramarr.get("sql");
Map<String,Object> result = new HashMap<String,Object>();
Matcher m = Pattern.compile("\\[(\\d+)\\]").matcher(sql);
if (m.find()) {
int time = Common.intval(m.group(1));
int temptime = (Integer) sGlobal.get("timestamp") - time;
StringBuffer buffer = new StringBuffer();
m.appendReplacement(buffer, temptime+"");
m.appendTail(buffer);
sql = buffer.toString();
}
paramarr.put("sql", sql);
String sqlstring = "SELECT"+sql.trim().replace(";","").replaceAll("(?i)^(select)", "");
if(Common.empty(paramarr.get("perpage"))) {
result.put("count", 1);
result.put("sql", sqlstring);
result.put("multi", "");
return result;
}
int listcount = 0;
String countsql = "";
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)\\sWHERE\\s(.+?)\\sORDER", 2, 3);
}
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)\\sWHERE\\s(.+?)\\sLIMIT", 2, 3);
}
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)\\sWHERE\\s(.+?)$", 2, 3);
}
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)\\sORDER", 2, -1);
}
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)\\sLIMIT", 2, -1);
}
if(Common.empty(countsql)) {
countsql = getcountsql(sqlstring, "SELECT\\s(.+?)\\sFROM\\s(.+?)$", 2, -1);
}
String multi = "";
if(!Common.empty(countsql)) {
listcount = dataBaseService.findRows(countsql);
if(listcount>0) {
int page = Math.max(Common.intval(request.getParameter("page")),1);
int perpage = Common.intval((String)paramarr.get("perpage"));
int start = (page-1)*perpage;
List<String> urlplus = new ArrayList<String>();
Map<String,String[]> values = (Map<String,String[]>)request.getParameterMap();
Set<String> keys = values.keySet();
for(String key:keys) {
if(!"page".equals(key)) urlplus.add(Common.urlEncode(key)+"="+Common.urlEncode(values.get(key)[0]));
}
String mpurl = request.getRequestURI().replace(".do", ".jsp")+(Common.empty(urlplus)?"":"?"+Common.implode(urlplus, "&"));
if(start >= listcount) {
page = listcount/perpage;
start = (page-1)*perpage;;
}
int maxPage = (Integer) sConfig.get("maxpage");
multi = Common.multi(request, listcount, perpage, page, maxPage, mpurl, null, null);
sqlstring = sqlstring.replaceAll("(?is) LIMIT(.+?)$", "");
sqlstring += " LIMIT "+start+","+paramarr.get("perpage");
}
}
result.put("count", listcount);
result.put("sql", sqlstring);
result.put("multi", multi);
return result;
}
private String getcountsql(String sqlstring, String rule, int tablename, int where) {
Matcher m = Pattern.compile("(?i)"+rule).matcher(sqlstring);
String countsql = "";
if(m.find()){
countsql = "SELECT COUNT(*) FROM "+m.group(tablename)+" WHERE "+(where<0 ? "1" : m.group(where));
}
return countsql;
}
@SuppressWarnings("unchecked")
private Map<String,Object> block_get(String cachekey,Map<String,Object>SGLOBAL,Map<String,Object>SCONFIG) {
Map<String,Object> caches = new HashMap<String,Object>();
caches.put("mtime", 0);
if("file".equals(SCONFIG.get("cachemode"))) {
String cachefile = JavaCenterHome.jchRoot+"./data/block_cache/"+getcachedirname(cachekey, "/",SCONFIG)+cachekey+".data";
File file = new File(cachefile);
if(file.exists()) {
String data = FileHelper.readFile(file);
List<Map<String,Object>> blockarr = (List<Map<String,Object>>)Serializer.unserialize(data);
Object multipage = blockarr.size()>0 ? blockarr.get(blockarr.size()-1).get("multipage"):"";
if(!Common.empty(multipage)) {
caches.put("multi", multipage);
blockarr.remove(blockarr.size()-1);
} else {
caches.put("multi", "");
}
caches.put("values", blockarr);
caches.put("mtime", (int)(file.lastModified()/1000));
}
} else {
String thetable = JavaCenterHome.getTableName("cache"+getcachedirname(cachekey,"",SCONFIG));
List<Map<String,Object>> resultList = dataBaseService.executeQuery("SELECT * FROM "+thetable+" WHERE cachekey = '"+cachekey+"'");
if(resultList!=null){
if(resultList.size()>0){
Map<String,Object> result = resultList.get(0);
List<Map<String,Object>> blockarr = (List<Map<String,Object>>)Serializer.unserialize((String)result.get("value"));
Object multipage = blockarr.size()>0 ? blockarr.get(blockarr.size()-1).get("multipage"):"";
if(!Common.empty(multipage)) {
caches.put("multi", multipage);
blockarr.remove(blockarr.size()-1);
} else {
caches.put("multi", "");
}
caches.put("values", blockarr);
caches.put("mtime", result.get("mtime"));
}
}else{
String basetable = JavaCenterHome.getTableName("cache");
List<Map<String,Object>> creatablelist = dataBaseService.executeQuery("SHOW CREATE TABLE "+basetable);
Map<String,Object> creattable = creatablelist.get(0);
String sql = ((String) creattable.get("Create Table")).replace(basetable,thetable);
dataBaseService.executeUpdate(sql);
}
}
return caches;
}
private String getcachedirname(String cachekey, String ext,Map<String,Object>SCONFIG) {
return Common.empty(SCONFIG.get("cachegrade"))?"":cachekey.substring(0, (Integer)SCONFIG.get("cachegrade"))+ext;
}
private void block_set(String cachekey, List<Map<String,Object>>blockarr,Map<String,Object>sGLOBAL,Map<String,Object>sConfig) {
String blockvalue = Serializer.serialize(blockarr);
if("file".equals(sConfig.get("cachemode"))){
boolean dircheck = false;
String cachedir = JavaCenterHome.jchRoot+"./data/block_cache/";
File dirfile = new File(cachedir);
if(!dirfile.isDirectory()){
dirfile.mkdir();
}
cachedir += getcachedirname(cachekey,"/",sConfig);
dirfile = new File(cachedir);
if(!dirfile.isDirectory()){
if(dirfile.mkdir()){
dircheck = true;
}
}else{
dircheck = true;
}
if(dircheck){
String cachefile = cachedir+cachekey+".data";
FileHelper.writeFile(cachefile, blockvalue.toString());
}
}else{
String thetable = JavaCenterHome.getTableName("cache"+getcachedirname(cachekey,"",sConfig));
dataBaseService.executeUpdate("REPLACE INTO "+thetable+" (cachekey, value, mtime) VALUES ('"+cachekey+"', '"+Common.sAddSlashes(blockvalue)+"', '"+sGLOBAL.get("timestamp")+"')");
}
}
}