/** * Most of the code in the Qalingo project is copyrighted Hoteia and licensed * under the Apache License Version 2.0 (release version 0.8.0) * http://www.apache.org/licenses/LICENSE-2.0 * * Copyright (c) Hoteia, 2012-2014 * http://www.hoteia.com - http://twitter.com/hoteia - contact@hoteia.com * */ package org.hoteia.qalingo.core.web.mvc.interceptor; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.hoteia.qalingo.core.Constants; import org.hoteia.qalingo.core.ModelConstants; import org.hoteia.qalingo.core.domain.CmsContent; import org.hoteia.qalingo.core.domain.Customer; import org.hoteia.qalingo.core.domain.Localization; import org.hoteia.qalingo.core.domain.Market; import org.hoteia.qalingo.core.domain.MarketArea; import org.hoteia.qalingo.core.domain.MarketPlace; import org.hoteia.qalingo.core.domain.CatalogCategoryMaster_; import org.hoteia.qalingo.core.domain.CatalogCategoryVirtual_; import org.hoteia.qalingo.core.domain.enumtype.FoUrls; import org.hoteia.qalingo.core.fetchplan.SpecificFetchMode; import org.hoteia.qalingo.core.i18n.enumtype.I18nKeyValueUniverse; import org.hoteia.qalingo.core.i18n.enumtype.ScopeCommonMessage; import org.hoteia.qalingo.core.i18n.enumtype.ScopeWebMessage; import org.hoteia.qalingo.core.i18n.message.CoreMessageSource; import org.hoteia.qalingo.core.pojo.GeolocData; import org.hoteia.qalingo.core.service.CatalogCategoryService; import org.hoteia.qalingo.core.service.CmsContentService; import org.hoteia.qalingo.core.service.EngineSessionService; import org.hoteia.qalingo.core.service.GeolocService; import org.hoteia.qalingo.core.service.MarketService; import org.hoteia.qalingo.core.service.ReferentialDataService; import org.hoteia.qalingo.core.service.UrlService; import org.hoteia.qalingo.core.web.mvc.factory.FrontofficeViewBeanFactory; import org.hoteia.qalingo.core.web.mvc.viewbean.CmsContentViewBean; import org.hoteia.qalingo.core.web.mvc.viewbean.MarketAreaViewBean; import org.hoteia.qalingo.core.web.mvc.viewbean.SeoDataViewBean; import org.hoteia.qalingo.core.web.resolver.RequestData; import org.hoteia.qalingo.core.web.util.RequestUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class PageModelDataHandlerInterceptor implements HandlerInterceptor { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired protected FrontofficeViewBeanFactory frontofficeViewBeanFactory; @Autowired protected EngineSessionService engineSessionService; @Autowired protected ReferentialDataService referentialDataService; @Autowired protected CatalogCategoryService catalogCategoryService; @Autowired protected MarketService marketService; @Autowired protected GeolocService geolocService; @Autowired protected CmsContentService cmsContentService; @Autowired protected UrlService urlService; @Autowired protected RequestUtil requestUtil; @Autowired protected CoreMessageSource coreMessageSource; @Value("${cookie.prefix}") protected String cookiePrefix; @Value("${minify.assets}") protected String minifyAssets; @Value("${assets.version}") protected String assetsVersion; protected List<SpecificFetchMode> categoryVirtualFetchPlans = new ArrayList<SpecificFetchMode>(); public PageModelDataHandlerInterceptor() { categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.catalogCategories.getName())); categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.parentCatalogCategory.getName())); categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.attributes.getName())); categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.categoryMaster.getName())); categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.categoryMaster.getName() + "." + CatalogCategoryMaster_.catalogCategoryType.getName())); categoryVirtualFetchPlans.add(new SpecificFetchMode(CatalogCategoryVirtual_.categoryMaster.getName() + "." + CatalogCategoryMaster_.attributes.getName())); } @Override public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, Object handler) throws Exception { return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception { } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { try { final RequestData requestData = requestUtil.getRequestData(request); final GeolocData geolocData = requestData.getGeolocData(); final MarketPlace currentMarketPlace = requestData.getMarketPlace(); final MarketArea currentMarketArea = requestData.getMarketArea(); final Localization currentLocalization = requestData.getMarketAreaLocalization(); final Locale locale = requestData.getLocale(); final Customer customer = requestData.getCustomer(); final String currentUrl = requestUtil.getCurrentRequestUrl(request); if(modelAndView != null){ String requestParamMinifyAssets = request.getParameter("minifyAssets"); if(StringUtils.isNotEmpty(requestParamMinifyAssets)){ request.getSession().setAttribute("minifyAssets", requestParamMinifyAssets); } String sessionMinifyAssets = (String) request.getSession().getAttribute("minifyAssets"); if(StringUtils.isNotEmpty(sessionMinifyAssets)){ modelAndView.getModelMap().put("minifyAssets", BooleanUtils.toBoolean(sessionMinifyAssets)); } else { modelAndView.getModelMap().put("minifyAssets", minifyAssets); } modelAndView.getModelMap().put("assetsVersion", assetsVersion); // SANITY CHECK : Controle MarketArea String referer = request.getHeader(Constants.REFERER); if(StringUtils.isEmpty(referer) || !referer.contains("coloroptical.com")){ // VISITOR COME FROM OTHER WEBSITE : check the target if(geolocData != null && geolocData.getCountry() != null && currentMarketArea != null && StringUtils.isNotEmpty(geolocData.getCountry().getIsoCode()) && !geolocData.getCountry().getIsoCode().equals(currentMarketArea.getGeolocCountryCode())){ // TARGET IS NOT THE GEOLOCATED MARKET AREA String targetUrl = request.getRequestURI().replace(request.getContextPath(), ""); // System.out.println("need redirect modal"); // System.out.println("targetUrl: " + targetUrl); MarketArea marketAreaGeoloc = null; List<MarketArea> marketAreas = marketService.findMarketAreaOpenedByGeolocCountryCode(geolocData.getCountry().getIsoCode()); if (marketAreas != null) { if (marketAreas.size() == 1) { marketAreaGeoloc = marketAreas.get(0); } else { // WE HAVE MANY MARKET AREA FOR THE CURRENT COUNTRY CODE - WE SELECT THE DEFAULT MARKET PLACE ASSOCIATE for (MarketArea marketAreaIt : marketAreas) { if (marketAreaIt.getMarket().getMarketPlace().isDefault()) { marketAreaGeoloc = marketAreaIt; } } } String context = "/" + marketAreaGeoloc.getCode() + "/" + marketAreaGeoloc.getDefaultLocalization().getCode() + "/"; String newSegmentl = urlService.getSeoSegmentMain(marketAreaGeoloc.getDefaultLocalization().getLocale(), true); String[] splits = request.getRequestURI().split("/"); String target = ""; int count = 0; for (String split : splits) { if (count == (splits.length - 1)) { target = split; } count++; } String newUrl = context.toLowerCase() + newSegmentl + "/" + target; String newAbsoluteUrl = urlService.buildAbsoluteUrl(requestData, newUrl); logger.debug("Redirect to: " + newAbsoluteUrl); try { // TEST TARGET URL URL obj = new URL(newAbsoluteUrl); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("User-Agent", request.getHeader("User-Agent")); int responseCode = con.getResponseCode(); if(responseCode != 200){ logger.debug("Url is not OK/200, url: " + newAbsoluteUrl); MarketAreaViewBean marketAreaGeolocViewBean = frontofficeViewBeanFactory.buildViewBeanMarketArea(requestData, currentMarketArea); newAbsoluteUrl = urlService.buildAbsoluteUrl(requestData, marketAreaGeolocViewBean.getChangeContextUrl()); logger.debug("Switch URL target, new url: " + newAbsoluteUrl); } } catch (Exception e) { // TODO: handle exception } modelAndView.getModelMap().put("newAbsoluteUrl", newAbsoluteUrl); modelAndView.getModelMap().put("redirectMarketArea", true); modelAndView.getModelMap().put("redirectMarketAreaCountry", referentialDataService.getCountryByLocale(geolocData.getCountry().getIsoCode(), locale)); modelAndView.getModelMap().put("targetMarketAreaCountry", referentialDataService.getCountryByLocale(currentMarketArea.getGeolocCountryCode(), locale)); } else { logger.debug("There is no MarketArea for this country:" + geolocData.getCountry().getIsoCode()); } } } boolean displayHttpsNavBarMessage = false; if(currentUrl.contains("login")){ displayHttpsNavBarMessage = true; } Cookie[] cookies = request.getCookies(); if (cookies != null) { Cookie navBarMessageCookie = null; boolean found = false; String navBarMessageName = cookiePrefix + "_NAV_BAR_MESSAGE"; for (Cookie cookie : cookies) { if (navBarMessageName.equals(cookie.getName())) { navBarMessageCookie = cookie; found = true; break; } } if(found && navBarMessageCookie.getValue().equals("hide")){ displayHttpsNavBarMessage = false; } } modelAndView.getModelMap().put("displayHttpsNavBarMessage", displayHttpsNavBarMessage); if(geolocData != null && geolocData.getCity() != null && StringUtils.isNotEmpty(geolocData.getCity().getName())){ modelAndView.getModelMap().addAttribute("cityName", geolocData.getCity().getName()); modelAndView.getModelMap().addAttribute("isGeolocated", true); } modelAndView.getModelMap().put(ModelConstants.LEGAl_TERMS_VIEW_BEAN, frontofficeViewBeanFactory.buildViewBeanLegalTerms(requestData)); modelAndView.getModelMap().put(ModelConstants.HEADER_CART, frontofficeViewBeanFactory.buildViewBeanHeaderCart(requestData)); // MARKETS FOR THE CURRENT MARKETPLACE Set<Market> marketList = currentMarketPlace.getMarkets(); List<MarketAreaViewBean> allMarketAreaViewBeans = new ArrayList<MarketAreaViewBean>(); for (Market market : marketList) { Set<MarketArea> marketAreaList = market.getMarketAreas(); for (MarketArea marketArea : marketAreaList) { if (marketArea.isOpened()) { MarketArea reloadedMarketArea = marketService.getMarketAreaById(marketArea.getId()); MarketAreaViewBean marketAreaViewBean = frontofficeViewBeanFactory.buildViewBeanMarketArea(requestData, reloadedMarketArea); if(currentMarketArea.getId().equals(reloadedMarketArea.getId())){ marketAreaViewBean.setActive(true); } allMarketAreaViewBeans.add(marketAreaViewBean); } } } // MARKET AREAS FOR THE CURRENT MARKET modelAndView.getModelMap().put(ModelConstants.MARKET_AREAS_VIEW_BEAN, allMarketAreaViewBeans); // CURRENT MARKET AREA modelAndView.getModelMap().put(ModelConstants.MARKET_AREA_VIEW_BEAN, frontofficeViewBeanFactory.buildViewBeanMarketArea(requestData, currentMarketArea)); // LOCALIZATIONS FOR THE CURRENT MARKET AREA modelAndView.getModelMap().put("marketAreaLocalization", frontofficeViewBeanFactory.buildViewBeanLocalization(requestData, currentLocalization)); modelAndView.getModelMap().put(ModelConstants.MARKET_AREA_LANGUAGES_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanLocalizationByMarketArea(requestData, currentLocalization)); // RETAILERS FOR THE CURRENT MARKET AREA modelAndView.getModelMap().put(ModelConstants.MARKET_AREA_RETAILERS_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanRetailerByMarketArea(requestData)); // CURRENCIES FOR THE CURRENT MARKET AREA modelAndView.getModelMap().put(ModelConstants.MARKET_AREA_CURRENCIES_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanCurrenciesByMarketArea(requestData)); // HEADER modelAndView.getModelMap().put(ModelConstants.HEADER_NAVS_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanHeaderNav(requestData)); modelAndView.getModelMap().put(ModelConstants.HEADER_MENUS_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanCmsMenus(requestData)); // FOOTER modelAndView.getModelMap().put(ModelConstants.FOOTER_MENUS_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanFooterMenu(requestData)); modelAndView.getModelMap().put(ModelConstants.FOOTER_NAVS_VIEW_BEAN, frontofficeViewBeanFactory.buildListViewBeanFooterNav(requestData)); //TODO a remonter dans CommonViewBean modelAndView.getModelMap().put("checkoutShoppingCartUrl", urlService.generateUrl(FoUrls.CART_DETAILS, requestData)); final List<Long> lastCmsContentIds = cmsContentService.findLastActiveCmsContentIds(CmsContent.APP_NAME_FRONTOFFICE_B2C, "ARTICLE", currentMarketArea.getId(), currentLocalization.getId(), 20); final List<CmsContent> reloadedCmsContents = new ArrayList<CmsContent>(); final Date now = new Date(); for (Iterator<Long> iterator = lastCmsContentIds.iterator(); iterator.hasNext();) { Long cmsContentId = (Long) iterator.next(); if(reloadedCmsContents.size() == 9){ // WE HAVE LOAD 20 items WITHOUT PARAM PUBLISH DATE, WE FILTER AFTER // TODO : specific query to load 9 items already publish and active break; } CmsContent reloadedCmsContent = cmsContentService.getCmsContentById(cmsContentId); if(reloadedCmsContent.getDatePublish().getTime() < now.getTime()){ reloadedCmsContents.add(reloadedCmsContent); } } final List<CmsContentViewBean> cmsContentViewBeans = frontofficeViewBeanFactory.buildListViewBeanCmsContent(requestData, reloadedCmsContents); if(cmsContentViewBeans != null && !cmsContentViewBeans.isEmpty()){ modelAndView.getModelMap().put("footerLastArticles", cmsContentViewBeans); } modelAndView.getModelMap().put("allArticleUrl", urlService.generateUrl(FoUrls.ARTICLES, requestData)); // GEOLOC // if(requestData.getGeolocData() != null){ // modelAndView.getModelMap().put(ModelConstants.GEOLOC_REMOTE_ADDRESS, requestData.getGeolocData().getRemoteAddress()); // modelAndView.getModelMap().put(ModelConstants.GEOLOC_COUNTRY, requestData.getGeolocData().getCountry()); // modelAndView.getModelMap().put(ModelConstants.GEOLOC_CITY, requestData.getGeolocData().getCity()); // } // APP NAME modelAndView.getModelMap().addAttribute(Constants.APP_NAME, requestUtil.getAppName(request)); Object[] appNameParams = {StringUtils.capitalize(requestUtil.getApplicationName())}; modelAndView.getModelMap().addAttribute(Constants.APP_NAME_HTML, coreMessageSource.getCommonMessage(ScopeCommonMessage.APP.getPropertyKey(), "name_html", appNameParams, locale)); modelAndView.getModelMap().addAttribute(ModelConstants.LOCALE_LANGUAGE_CODE, locale.getLanguage()); modelAndView.getModelMap().addAttribute(ModelConstants.CONTEXT_PATH, request.getContextPath()); modelAndView.getModelMap().addAttribute(ModelConstants.THEME, requestUtil.getCurrentTheme(request)); Object[] params = {StringUtils.capitalize(requestUtil.getEnvironmentName())}; modelAndView.getModelMap().addAttribute(ModelConstants.ENV_NAME, coreMessageSource.getSpecificMessage(I18nKeyValueUniverse.FO.getPropertyKey(), ScopeWebMessage.COMMON.getPropertyKey(), "header.env.name", params, locale)); if(!modelAndView.getModelMap().containsAttribute(ModelConstants.SEO_DATA_VIEW_BEAN)){ SeoDataViewBean seoData = frontofficeViewBeanFactory.buildViewSeoData(requestData); if(modelAndView.getModelMap().containsAttribute(ModelConstants.PAGE_TITLE)){ String pageTitle = (String) modelAndView.getModelMap().get(ModelConstants.PAGE_TITLE); seoData.setMetaOgTitle(pageTitle); seoData.setPageTitle(pageTitle); } modelAndView.getModelMap().put(ModelConstants.SEO_DATA_VIEW_BEAN, seoData); } modelAndView.getModelMap().put(ModelConstants.URL_SUBMIT_QUICK_SEARCH, urlService.generateUrl(FoUrls.CATALOG_SEARCH, requestUtil.getRequestData(request))); String currentRequestUrl = requestUtil.getCurrentRequestUrl(request); if(modelAndView.getModelMap().get(ModelConstants.ALTERNATE_LINKS_VIEW_BEAN) == null){ System.out.println("!!!!! THIS URL NEED AN alternate: " + currentRequestUrl); } // // Alternate Links // if(modelAndView.getModelMap().get(ExtModelConstants.ALTERNATE_LINKS_VIEW_BEAN) == null){ // String currentRequestUrl = requestUtil.getCurrentRequestUrl(request); // List<HeadLinkViewBean> alternateLinks = new ArrayList<HeadLinkViewBean>(); // if(currentRequestUrl.contains("article")){ // // } else { // // default // for (MarketAreaViewBean marketAreaViewBean : allMarketAreaViewBeans) { // for (LocalizationViewBean localizationViewBean : marketAreaViewBean.getLocalizations()) { // if(!marketAreaViewBean.getCode().equals(currentMarketArea.getCode())){ // String splitUrl[] = currentRequestUrl.split("/"); // String alternateUrl = "/" + marketAreaViewBean.getCode().toLowerCase() + "/" + localizationViewBean.getCode(); // for (int i = 3; i < splitUrl.length; i++) { // alternateUrl = alternateUrl + "/" + splitUrl[i]; // } // String hreflang = localizationViewBean.getLocaleCode().replace("_", "-"); // if(marketAreaViewBean.getCode().equals("INT") && localizationViewBean.getCode().equals("en")){ // hreflang = "x-default"; // } // HeadLinkViewBean metaLink = new HeadLinkViewBean("alternate", hreflang, alternateUrl); // alternateLinks.add(metaLink); // } // } // } // } // if(!alternateLinks.isEmpty()){ // modelAndView.getModelMap().addAttribute("alternateLinks", alternateLinks); // } // } } } catch (Exception e) { logger.error("Inject common datas failed", e); } } }