package com.anjlab.ping.filters; import static com.anjlab.ping.services.AppModule.buildGAECache; import static com.anjlab.ping.services.AppModule.buildMemcacheService; import static com.anjlab.ping.services.AppModule.buildQuotaDetails; import java.io.IOException; import javax.cache.Cache; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.tapestry5.EventContext; import org.apache.tapestry5.Link; import org.apache.tapestry5.internal.services.BaseURLSourceImpl; import org.apache.tapestry5.internal.services.DefaultSessionPersistedObjectAnalyzer; import org.apache.tapestry5.internal.services.LinkImpl; import org.apache.tapestry5.internal.services.LinkSecurity; import org.apache.tapestry5.internal.services.RequestGlobalsImpl; import org.apache.tapestry5.internal.services.RequestImpl; import org.apache.tapestry5.internal.services.ResponseImpl; import org.apache.tapestry5.internal.services.TapestrySessionFactoryImpl; import org.apache.tapestry5.services.PageRenderLinkSource; import org.apache.tapestry5.services.RequestGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.anjlab.gae.LocalMemorySoftCache; import com.anjlab.gae.QuotaDetails; import com.anjlab.ping.services.Application; import com.anjlab.ping.services.JobExecutor; import com.anjlab.ping.services.Mailer; import com.anjlab.ping.services.dao.JobDAO; import com.anjlab.ping.services.dao.impl.cache.JobDAOImplCache; public abstract class AbstractFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(AbstractFilter.class); protected EntityManagerFactory emf; protected Application application; protected JobDAO jobDAO; protected final RequestGlobals globals = new RequestGlobalsImpl(); protected Cache cache; protected QuotaDetails quotaDetails; public AbstractFilter() { super(); } @Override public void init(FilterConfig config) throws ServletException { cache = buildGAECache(logger, null); quotaDetails = buildQuotaDetails(cache, buildMemcacheService(logger)); } @SuppressWarnings("rawtypes") protected void lazyInit() { // One instance might already be created by tapestry-jpa System.setProperty("appengine.orm.disable.duplicate.emf.exception", ""); emf = Persistence.createEntityManagerFactory("transactions-optional"); jobDAO = new JobDAOImplCache(cache); application = new Application(null, jobDAO, null, null, new JobExecutor(), new Mailer(), new PageRenderLinkSource() { @Override public Link createPageRenderLinkWithContext(Class pageClass, EventContext eventContext) { return null; } @Override public Link createPageRenderLinkWithContext(String pageName, EventContext eventContext) { return null; } @Override public Link createPageRenderLinkWithContext(String pageName, Object... context) { return null; } @Override public Link createPageRenderLink(String pageName) { return null; } @Override public Link createPageRenderLink(Class pageClass) { String pageAddress = pageClass.getName().substring(Application.APP_PAGES_PACKAGE.length()).replaceAll("\\.", "/"); return new LinkImpl(pageAddress, false, LinkSecurity.INSECURE, new ResponseImpl(globals.getHTTPServletRequest(), globals.getHTTPServletResponse()), null, new BaseURLSourceImpl(globals.getRequest(), "", 0, 0)); } @Override public Link createPageRenderLinkWithContext(Class pageClass, Object... context) { StringBuilder pageAddress = new StringBuilder(pageClass.getName().substring(Application.APP_PAGES_PACKAGE.length()).replaceAll("\\.", "/")); for (Object object : context) { pageAddress.append("/"); pageAddress.append(object); } return new LinkImpl(pageAddress.toString(), false, LinkSecurity.INSECURE, new ResponseImpl(globals.getHTTPServletRequest(), globals.getHTTPServletResponse()), null, new BaseURLSourceImpl(globals.getRequest(), "", 0, 0)); } }, globals, null, null); } public void setApplication(Application application) { this.application = application; } @Override public void destroy() { } protected abstract void processRequest(EntityTransaction tx) throws Exception; protected boolean disableFilter() { // logger.warn("Temporarily disabling all filters"); return false; } @Override public synchronized void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long startTime = System.currentTimeMillis(); EntityManager em = null; EntityTransaction tx = null; try { if (disableFilter()) { logger.debug("Filter disabled for request: {}", ((HttpServletRequest) request).getRequestURI()); return; } if (emf == null) { lazyInit(); } em = emf.createEntityManager(); tx = em.getTransaction(); tx.begin(); jobDAO.setEntityManager(em); HttpServletRequest httpServletRequest = (HttpServletRequest)request; HttpServletResponse httpServletResponse = (HttpServletResponse)response; globals.storeServletRequestResponse(httpServletRequest, httpServletResponse); globals.storeRequestResponse(new RequestImpl(httpServletRequest, httpServletRequest.getCharacterEncoding(), new TapestrySessionFactoryImpl( true, new DefaultSessionPersistedObjectAnalyzer(), httpServletRequest)), new ResponseImpl(httpServletRequest, httpServletResponse)); processRequest(tx); if (tx.isActive()) { tx.commit(); } } catch (Exception e) { logger.error("Error processing request", e); quotaDetails.checkOverQuotaException(e); } finally { if (cache instanceof LocalMemorySoftCache) { ((LocalMemorySoftCache) cache).reset(); } if (tx != null && tx.isActive()) { tx.rollback(); } if (em != null) { em.close(); } long endTime = System.currentTimeMillis(); logger.debug("Total time: " + (endTime - startTime)); } } }