package com.google.sitebricks; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.inject.servlet.RequestScoped; import com.google.sitebricks.compiler.Compilers; import com.google.sitebricks.routing.PageBook; import com.google.sitebricks.routing.Production; import com.google.sitebricks.routing.SystemMetrics; import net.jcip.annotations.ThreadSafe; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * Used in the development stage to intercept the real pagebook so we can reload * & recompile templates on demand. * * @author Dhanji R. Prasanna (dhanji@gmail com) */ @ThreadSafe @Singleton class DebugModePageBook implements PageBook { private final PageBook book; private final SystemMetrics metrics; private final Compilers compilers; private final Provider<Memo> memo; @Inject public DebugModePageBook(@Production PageBook book, SystemMetrics metrics, Compilers compilers, Provider<Memo> memo) { this.book = book; this.metrics = metrics; this.compilers = compilers; this.memo = memo; } public Page at(String uri, Class<?> myPageClass) { return book.at(uri, myPageClass); } public Page get(String uri) { final Page page = book.get(uri); //reload template reload(uri, page); return page; } public Page forName(String name) { final Page page = book.forName(name); //reload template reload(name, page); return page; } public Page embedAs(Class<?> page, String as) { return book.embedAs(page, as); } @Override public Page decorate(Class<?> pageClass) { return book.decorate(pageClass); } public Page nonCompilingGet(String uri) { // Simply delegate thru to the real page book. return book.get(uri); } public Page forInstance(Object instance) { return book.forInstance(instance); } public Page forClass(Class<?> pageClass) { return book.forClass(pageClass); } public Page serviceAt(String uri, Class<?> pageClass) { return book.serviceAt(uri, pageClass); } public Collection<List<Page>> getPageMap() { return book.getPageMap(); } @Override public void at(String uri, List<ActionDescriptor> actionDescriptor, Map<Class<? extends Annotation>, String> methodSet) { book.at(uri, actionDescriptor, methodSet); } private void reload(String identifier, Page page) { // Do nothing on the first pass since the page is already compiled. // Also skips static resources and headless web services. if (null == page || !metrics.isActive() || page.isHeadless()) return; // Ensure we reload only once per request, per identifier. final Memo memo = this.memo.get(); if (memo.uris.contains(identifier)) return; // Otherwise, remember that we already loaded it in this request. memo.uris.add(identifier); // load template and compile compilers.compilePage(page); } @RequestScoped private static class Memo { private final Set<String> uris = new HashSet<String>(); } }