package http.server; import http.resource.ErrorHandleResouce; import http.resource.RedirectCurrentUserResouce; import http.resource.RedirectResouce; import http.startup.Configurable; import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import nebula.data.Entity; import nebula.server.Resource; import nebula.server.ResourceEngine; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.URIUtil; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; import com.google.common.collect.Maps; public class BasicResourceContainer extends AbstractHandler { private Log log = LogFactory.getLog(this.getClass()); final private LoadingCache<String, Resource> cachedLinks; final private Map<String, ResourceEngine> engines; final ResourceEngine defaultEngine; final RedirectCurrentUserResouce redirectCurrentUserResouce; final RedirectResouce redirectToLoginResouce; final ErrorHandleResouce errorHandleResource; CacheLoader<String, Resource> loader = new CacheLoader<String, Resource>() { public Resource load(String path) throws Exception { log.info("load resource - " + path); Resource res = null; int idx = path.indexOf('/', 1); if (idx > 0) { String key = path.substring(1, idx); ResourceEngine engine = engines.get(key); if (engine != null) res = engine.resolve(path); if (res != null) return res; res = defaultEngine.resolve(path); } else { res = defaultEngine.resolve(path); } return res; } }; RemovalListener<String, Resource> removalListener = new RemovalListener<String, Resource>() { public void onRemoval(RemovalNotification<String, Resource> removal) { log.info("remove " + removal.getKey()); } }; @Inject public BasicResourceContainer(final Configurable<BasicResourceContainer> conf) { engines = Maps.newHashMap(); conf.configure(this); this.defaultEngine = engines.get("*"); this.errorHandleResource = new ErrorHandleResouce(); this.redirectCurrentUserResouce = new RedirectCurrentUserResouce(); this.redirectToLoginResouce = new RedirectResouce("/login.html"); cachedLinks = CacheBuilder.newBuilder().build(loader); cachedLinks.put("/", redirectCurrentUserResouce); } public void register(String match, ResourceEngine engine) { // String regexMatch = match.replace(".", "[\\.]").replace("*", ".*"); for (String key : match.split(" ")) { if (key.length() > 0) { engines.put(key, engine); } } } @Override public void handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { if (log.isDebugEnabled()) { log.debug("client request "+req.getMethod() +" - " + req.getPathInfo() + (req.getQueryString()==null?"":(" - " + URIUtil.decodePath(req.getQueryString())))); } try { String path = req.getPathInfo(); Entity currentUser = (Entity) req.getSession().getAttribute("#currentUser"); if (currentUser != null || "TRUE".equals(req.getParameter("Debug"))) { Resource res = cachedLinks.get(path); res.handle(req, resp); } else { if ("/".equals(path)) { redirectToLoginResouce.handle(req, resp); return; } int idx = path.indexOf('/', 1); if (idx < 0) { } else { String key = path.substring(1, idx); if ("js css lib e font img images f".indexOf(key) > 0) { } else { redirectToLoginResouce.handle(req, resp); return; } } Resource res = cachedLinks.get(path); res.handle(req, resp); } return; } catch (ExecutionException e) { log.error(e); } catch (IOException e) { log.error(e); } catch (ServletException e) { log.error(e); } catch (RuntimeException e) { log.error(e.getClass().getName(), e); } resp.setStatus(400); resp.flushBuffer(); } }