package com.aggrepoint.winlet.site;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.javamail.ConfigurableMimeFileTypeMap;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import com.aggrepoint.winlet.AuthorizationEngine;
import com.aggrepoint.winlet.Context;
import com.aggrepoint.winlet.PsnRuleEngine;
import com.aggrepoint.winlet.site.domain.Branch;
import com.aggrepoint.winlet.site.domain.Page;
/**
*
* @author Jiangming Yang (yangjm@gmail.com)
*/
@Controller
public class SiteController {
static final Log logger = LogFactory.getLog(SiteController.class);
static final int CHECK_UPDATE_INTERVAL = 2000;
static ServletContext context;
static FileSystemCfgLoader loader;
/** 分支配置 */
static ArrayList<Branch> branches;
public static final String PAGE_PATH = "PAGE_PATH";
public static final String PATH_EXPAND = "PATH_EXPAND";
public static final String PAGE_DATA = "PAGE_DATA";
private static void updateBranches(String contextRoot) {
if (context == null)
context = Context.get().getBean(ServletContext.class);
if (loader == null)
loader = new FileSystemCfgLoader(
context.getRealPath("/WEB-INF/site/branch"),
CHECK_UPDATE_INTERVAL);
branches = loader.load(branches, contextRoot);
}
public static Branch getBranch(AuthorizationEngine ap, String contextRoot) {
updateBranches(contextRoot);
Branch branch = null;
for (Branch b : branches) {
try {
if (ap.check(b) == null) {
branch = b;
break;
}
} catch (Exception e) {
logger.error(
"Error evaluating branch access rule \"" + b.getRule()
+ "\".", e);
}
}
return branch;
}
public static Page getPage(AuthorizationEngine ap, String path,
String contextRoot) {
updateBranches(contextRoot);
Branch branch = null;
for (Branch b : branches) {
try {
if (ap.check(b) == null) {
branch = b;
break;
}
} catch (Exception e) {
logger.error(
"Error evaluating branch access rule \"" + b.getRule()
+ "\".", e);
}
}
if (branch == null)
return null;
return branch.findPage(path, ap);
}
static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 100];
int n = 0;
while (-1 != (n = input.read(buffer)))
baos.write(buffer, 0, n);
return baos.toByteArray();
}
static ConfigurableMimeFileTypeMap FILE_TYPE_MAP = new ConfigurableMimeFileTypeMap();
static Object returnFile(Branch branch, String path) throws IOException {
File file = new File(branch.getPath() + path);
if ((!file.exists() || file.isDirectory()) && branch.getIndex() != null)
file = new File(branch.getPath() + branch.getIndex());
if (!file.exists() || file.isDirectory())
return "/WEB-INF/site/error/pagenotfound.jsp";
InputStream in = new FileInputStream(file);
final HttpHeaders headers = new HttpHeaders();
try {
headers.setContentType(MediaType.valueOf(FILE_TYPE_MAP
.getContentType(file)));
} catch (Exception e) {
headers.setContentType(MediaType
.valueOf("application/octet-stream"));
}
byte[] bytes = toByteArray(in);
in.close();
return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.CREATED);
}
/**
* urlPrefix - 前段HTTP服务器或者反向代理添加的URL前段,例如/portal/site/home
*/
@RequestMapping(value = "/site/**")
public Object site(
HttpServletRequest req,
HttpServletResponse resp,
AuthorizationEngine ap,
PsnRuleEngine psnEngine,
@RequestHeader(value = "X-Url-Prefix", required = false) String urlPrefix) {
String path = req.getServletPath().substring(5);
try {
Branch branch = getBranch(ap, req.getServletContext()
.getContextPath());
if (branch == null) {
return "/WEB-INF/site/error/pagenotfound.jsp";
}
if (branch.isStatic()) { // 静态分支,直接返回要访问的资源
if (path.equals("/cfg.cfg")) // 不允许访问cfg.cfg
path = "";
return returnFile(branch, path);
} else {
Page page = branch.findPage(path, ap);
if (page == null)
return "/WEB-INF/site/error/pagenotfound.jsp";
if (page.getLink() != null)
return "redirect:" + page.getLink();
if (page.isStatic()) {
if (path.equals(page.getFullPath() + "cfg.cfg")) // 不允许访问cfg.cfg
return "/WEB-INF/site/error/pagenotfound.jsp";
return returnFile(branch,
path.replace(page.getFullPath(), page.getFullDir()));
} else {
SiteContext sc = new SiteContext(req, page, urlPrefix);
req.setAttribute(SiteContext.SITE_CONTEXT_KEY, sc);
req.setAttribute(PAGE_PATH,
sc.getPageUrl(page.getFullPath()));
req.setAttribute(PAGE_DATA, page.getDataMap());
if (page.isExpand() && !page.getFullPath().equals(path)
&& path.startsWith(page.getFullPath()))
req.setAttribute(PATH_EXPAND,
path.substring(page.getFullPath().length()));
return "/WEB-INF/site/template/"
+ page.getPsnTemplate(psnEngine) + ".jsp";
}
}
} catch (Exception e) {
return "/WEB-INF/site/error/pagenotfound.jsp";
}
}
}