package es.alvsanand.webpage.web.filters; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.cache.Cache; import javax.cache.CacheException; import javax.cache.CacheFactory; import javax.cache.CacheManager; 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.commons.lang.StringUtils; import es.alvsanand.webpage.common.Logger; import es.alvsanand.webpage.common.UAgentInfo; import es.alvsanand.webpage.init.DBInitiator; import es.alvsanand.webpage.web.mobile.config.MobileConfig; public class MobileFilter implements Filter { private final static Logger logger = new Logger(MobileFilter.class); private final static String USER_AGENT_HTTP_HEADER = "User-Agent"; private final static String ACCEPT_HTTP_HEADER = "Accept"; private final static String CONFIG_FILE = "es.alvsanand.webpage.web.mobile.config.MobileConfig"; private final static String WEB_INF_DIR = "/WEB-INF"; private final static String DEFAULT_CONFIG_FILE = WEB_INF_DIR + "/" + "security-config.xml"; private MobileConfig mobileConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { loadConfig(filterConfig); (new DBInitiator()).init(); logger.info("MobileFilter initiated successfully"); } public void loadConfig(FilterConfig filterConfig) { mobileConfig = getMobileConfigFromCache(); if (mobileConfig == null) { String configFile = filterConfig.getServletContext().getInitParameter(CONFIG_FILE); if (configFile == null || configFile.length() == 0) { configFile = DEFAULT_CONFIG_FILE; } InputStream inputStream = filterConfig.getServletContext().getResourceAsStream(configFile); try { mobileConfig = MobileConfig.unmarshal(new InputStreamReader(inputStream)); putMobileConfigFromCache(mobileConfig); } catch (Exception e) { logger.error("Error loading MobileConfig"); throw new IllegalArgumentException("MobileConfig is not correct"); } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { if (mobileConfig == null) { throw new IllegalArgumentException("SecurityConfig is not correct"); } HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest; HttpServletResponse httpServletResponse = (HttpServletResponse)servletResponse; String url = httpServletRequest.getRequestURI(); logger.debug("Executing MobileFilter for url " + url); Map<String, String> headers = getHeaderMap(httpServletRequest); String userAgent = headers.get(USER_AGENT_HTTP_HEADER); String httpAccept = headers.get(ACCEPT_HTTP_HEADER); UAgentInfo uAgentInfo = new UAgentInfo(userAgent, httpAccept); try { Matcher m = (Pattern.compile(mobileConfig.getNoMobilePattern())).matcher(url); if (m.matches() && uAgentInfo.isSmartphone()) { boolean end = false; for(String pattern: mobileConfig.getExcludedResources().getUrlPattern()){ if(url.matches(pattern)){ end = true; break; } } if (!end && StringUtils.isNotEmpty(userAgent) && StringUtils.isNotEmpty(httpAccept)) { String result = mobileConfig.getDefaultURL(); httpServletResponse.sendRedirect(result); return; } } } catch (Exception e) { logger.error("Error executing MobileFilter for url " + url); } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { logger.info("Destroying MobileFilter"); } private es.alvsanand.webpage.web.mobile.config.MobileConfig getMobileConfigFromCache() { Cache cache = null; try { CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory(); cache = cacheFactory.createCache(Collections.emptyMap()); return (es.alvsanand.webpage.web.mobile.config.MobileConfig) cache.get(es.alvsanand.webpage.web.mobile.config.MobileConfig.class .getName()); } catch (CacheException cacheException) { logger.error("Error in getting MobileConfig from cache.", cacheException); return null; } catch(Exception exception){ if(cache!=null){ cache.remove(es.alvsanand.webpage.web.mobile.config.MobileConfig.class.getName()); } return null; } } private void putMobileConfigFromCache(es.alvsanand.webpage.web.mobile.config.MobileConfig mobileConfig) { Cache cache; try { CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory(); cache = cacheFactory.createCache(Collections.emptyMap()); cache.put(es.alvsanand.webpage.web.mobile.config.MobileConfig.class.getName(), mobileConfig); } catch (CacheException cacheException) { logger.error("Error in putting MobileConfig from cache.", cacheException); } } private Map<String, String> getHeaderMap(final HttpServletRequest request) { Map<String, String> headers = new HashMap<String, String>(); for (Enumeration<?> e = request.getHeaderNames(); e.hasMoreElements();) { String headerName = (String) e.nextElement(); headers.put(headerName, request.getHeader(headerName)); } return headers; } }