package br.com.caelum.guj.vraptor.filter; import java.io.IOException; 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 br.com.caelum.guj.repositories.TopicRepository; import br.com.caelum.guj.repositories.TopicRepositoryWrapper; import br.com.caelum.guj.uri.DefaultBookmarkableURIBuilder; import br.com.caelum.guj.uri.DefaultURICache; import br.com.caelum.guj.uri.PaginatedURIConverter; import br.com.caelum.guj.uri.URICache; import br.com.caelum.guj.uri.URIConverter; import br.com.caelum.guj.uri.bookmarkable.AllBookmarkableToCompatibleConverters; import br.com.caelum.guj.uri.bookmarkable.ConverterMatcher; import br.com.caelum.guj.uri.compatible.CompatibleToBookmarkablePostConverter; import br.com.caelum.guj.view.Slugger; public class BookmarkableURIFilter implements Filter { private URICache cache; private TopicRepository topicRepository; @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response= (HttpServletResponse) res; ConverterMatcher converters = new ConverterMatcher(AllBookmarkableToCompatibleConverters.get(request .getRequestURI())); if (converters.oneMatched()) { String compatibleURI = converters.getConverter().convert(); if (converters.shortBookmarkableURI()) { redirectUsingCache(request, response, compatibleURI); } else { setRequestAttributesToCanonicalLink(request, converters); request.getRequestDispatcher(compatibleURI).forward(request, response); } } else { chain.doFilter(request, response); } } private void setRequestAttributesToCanonicalLink(HttpServletRequest request, ConverterMatcher converters) { URIConverter converter = converters.getConverter(); String requestedTopicPage = ""; if (converter instanceof PaginatedURIConverter) { Integer topicPage = ((PaginatedURIConverter) converter).getPage(); if (topicPage != null && topicPage > 1) { requestedTopicPage = "/"+topicPage; } } request.setAttribute("requestedTopicPageBeforeForward", requestedTopicPage); request.setAttribute("bookmarkableURIBeforeForward", request.getRequestURI()); } private void redirectUsingCache(HttpServletRequest request, HttpServletResponse response, String compatibleURI) { String cachedBookmarkableURI = cache.getBookmarkableURI(compatibleURI); if (cachedBookmarkableURI == null) { cachedBookmarkableURI = compatibleURIToBookmarkableURI(compatibleURI, request); cache.put(compatibleURI, cachedBookmarkableURI); } redirectTo(response, cachedBookmarkableURI); } private String compatibleURIToBookmarkableURI(String compatibleURI, HttpServletRequest request) { CompatibleToBookmarkablePostConverter converter = new CompatibleToBookmarkablePostConverter(compatibleURI, topicRepository, new DefaultBookmarkableURIBuilder(new Slugger())); if (converter.isConvertable()) { return request.getContextPath() + converter.convert(); } return null; } private void redirectTo(HttpServletResponse response, String newUri) { response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); response.setHeader("Location", newUri); } @Override public void destroy() { } @Override public void init(FilterConfig config) throws ServletException { createURICache(config); createTopicRepository(config); } private void createURICache(FilterConfig config) throws ServletException { URICache cacheFromContext = (URICache) config.getServletContext().getAttribute("URICache"); if (cacheFromContext == null) { cache = new DefaultURICache(); config.getServletContext().setAttribute("URICache", cache); } else { this.cache = cacheFromContext; } } private void createTopicRepository(FilterConfig config) throws ServletException { String topicRepositoryClassName = config.getInitParameter("topicRepository"); if (topicRepositoryClassName == null) { topicRepository = new TopicRepositoryWrapper(); } else { try { topicRepository = (TopicRepository) Class.forName(topicRepositoryClassName).newInstance(); } catch (Exception e) { throw new ServletException(e); } } } }