package org.onehippo.forge.konakart.site.service.impl; import com.konakart.al.KKAppEng; import com.konakart.al.KKAppException; import com.konakart.app.FetchProductOptions; import com.konakart.app.KKException; import com.konakart.appif.CustomerTagIf; import com.konakart.appif.FetchProductOptionsIf; import org.apache.commons.lang.LocaleUtils; import org.apache.commons.lang.StringUtils; import org.hippoecm.hst.configuration.hosting.Mount; import org.hippoecm.hst.configuration.sitemap.HstSiteMapItem; import org.hippoecm.hst.core.component.HstComponentException; import org.hippoecm.hst.core.component.HstRequest; import org.hippoecm.hst.core.request.HstRequestContext; import org.onehippo.forge.konakart.common.engine.KKAdminEngine; import org.onehippo.forge.konakart.common.engine.KKEngine; import org.onehippo.forge.konakart.common.engine.KKStoreConfig; import org.onehippo.forge.konakart.common.jcr.HippoModuleConfig; import org.onehippo.forge.konakart.site.service.KKEngineService; import org.onehippo.forge.konakart.site.service.KKServiceHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.jcr.Session; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Locale; import static org.onehippo.forge.konakart.site.service.KKTagsService.TAG_PRODUCTS_VIEWED; public class KKEngineServiceImpl implements KKEngineService { private static Logger log = LoggerFactory.getLogger(KKEngineServiceImpl.class); @Override public KKAppEng getKKAppEng(@Nonnull HttpServletRequest servletRequest) { // Check if the Konakart engine has been created HttpSession session = servletRequest.getSession(); return (KKAppEng) session.getAttribute(KKAppEng.KONAKART_KEY); } /** * Retrieve the Konakart client or null if it is not found into the session * * @param request http request * @return the KonaKart client engine instance */ @Nullable public KKAppEng getKKAppEng(@Nonnull HstRequest request) { return (KKAppEng) request.getAttribute(KKAppEng.KONAKART_KEY); } @Override public KKAppEng initKKEngine(@Nonnull HttpServletRequest servletRequest, @Nonnull HttpServletResponse servletResponse, @Nonnull HstRequestContext requestContext, @Nonnull Session jcrSession, @Nonnull KKStoreConfig kkStoreConfig) throws HstComponentException { KKCookieServiceImpl kkCookieServiceImpl = new KKCookieServiceImpl(); KKAppEng kkAppEng = getKKAppEng(servletRequest); if (kkAppEng == null || !StringUtils.equalsIgnoreCase(kkStoreConfig.getStoreId(), kkAppEng.getStoreId())) { if (log.isInfoEnabled()) { log.info("KKEngine not found on the session"); } try { String storeId = kkStoreConfig.getStoreId(); // Create the Konakart engine kkAppEng = KKEngine.get(storeId); // Set the locale Locale preferredLocale = findPreferredLocale(requestContext); if (preferredLocale != null) { kkAppEng.setLocale(preferredLocale.toString()); } // initialize the Fetch production options FetchProductOptionsIf productOptions = new FetchProductOptions(); productOptions.setCatalogId(kkStoreConfig.getCatalogId()); productOptions.setUseExternalPrice(HippoModuleConfig.getConfig().getClientEngineConfig().isUseExternalPrice()); productOptions.setUseExternalQuantity(HippoModuleConfig.getConfig().getClientEngineConfig().isUseExternalQuantity()); kkAppEng.setFetchProdOptions(productOptions); if (log.isInfoEnabled()) { log.info("Set KKAppEng on the session for storeId " + storeId); } // Store the engine under the session servletRequest.getSession().setAttribute(KKAppEng.KONAKART_KEY, kkAppEng); // Keep this in the session. To be reused when the customer will switch the locale. servletRequest.getSession().setAttribute(KKAppEng.KONAKART_KEY + "-" + kkStoreConfig.getStoreId(), kkAppEng); // Create or retrieve the customer's cookie kkCookieServiceImpl.manageCookies(servletRequest, servletResponse, kkAppEng); // Retrieve the config. kkAppEng.refreshAllClientConfigs(); } catch (Exception e) { log.error("Failed to create Konakart engine ", e); throw new HstComponentException("Failed to create Konakart engine", e); } } return kkAppEng; } @Override public int validKKSession(@Nonnull HttpServletRequest servletRequest, @Nonnull HttpServletResponse servletResponse) throws HstComponentException { HttpSession session = servletRequest.getSession(); KKAppEng kkAppEng = (KKAppEng) session.getAttribute(KKAppEng.KONAKART_KEY); if (kkAppEng == null) { return -1; } try { // If the session is null, set the forward and return a negative number if (kkAppEng.getSessionId() == null) { return -1; } // If the user can't be logged-in, an exception if thrown try { // At this point we return a valid customer id return kkAppEng.getEng().checkSession(kkAppEng.getSessionId()); } catch (KKException e) { logOut(servletRequest, servletResponse); } } catch (Exception e) { log.warn("Unable to check the Konakart session - {} ", e.toString()); } return -1; } @Override public boolean logIn(HttpServletRequest request, HttpServletResponse response, String username, String password) { KKAppEng kkAppEng = getKKAppEng(request); if (kkAppEng == null) { return false; } try { int custId = validKKSession(request, response); // Check if the user is already logged in if (custId >= 0) { if (log.isDebugEnabled()) { log.debug("User already logged in"); } // Refresh the data relevant to the customer such as his basked and recent orders. kkAppEng.getCustomerMgr().refreshCustomerCachedData(); return true; } // Get recently viewed products before logging in CustomerTagIf prodsViewedTagGuest = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); // Login String result = kkAppEng.getCustomerMgr().login(username, password); if (result == null) { return false; } /* * Manage Cookies */ KKServiceHelper.getKKCookieService().manageCookiesLogin(request, response, kkAppEng); // Insert event KKServiceHelper.getKKEventService().insertCustomerEvent(request, KKEventServiceImpl.ACTION_CUSTOMER_LOGIN); // Set recently viewed products for the logged in customer if changed as guest CustomerTagIf prodsViewedTagCust = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); updateRecentlyViewedProducts(kkAppEng, prodsViewedTagGuest, prodsViewedTagCust); return true; } catch (Exception e) { log.warn("Unable to logged-in. Force to be logged-out", e); try { kkAppEng.getCustomerMgr().logout(); } catch (KKException e1) { // do nothing } } return false; } @Override public boolean loginByAdmin(HttpServletRequest request, HttpServletResponse response, int customerId) { KKAppEng kkAppEng = getKKAppEng(request); if (kkAppEng == null) { return false; } try { int custId = validKKSession(request, response); // Check if the user is already logged in if (custId >= 0) { if (log.isDebugEnabled()) { log.debug("User already logged in"); } // Refresh the data relevant to the customer such as his basked and recent orders. kkAppEng.getCustomerMgr().refreshCustomerCachedData(); return true; } // Get recently viewed products before logging in CustomerTagIf prodsViewedTagGuest = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); String adminSessionId = KKAdminEngine.getInstance().getSession(); // Login String result = kkAppEng.getCustomerMgr().loginByAdmin(adminSessionId, customerId); if (result == null) { return false; } /* * Manage Cookies */ KKServiceHelper.getKKCookieService().manageCookiesLogin(request, response, kkAppEng); // Insert event KKServiceHelper.getKKEventService().insertCustomerEvent(request, KKEventServiceImpl.ACTION_CUSTOMER_LOGIN); // Set recently viewed products for the logged in customer if changed as guest CustomerTagIf prodsViewedTagCust = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); updateRecentlyViewedProducts(kkAppEng, prodsViewedTagGuest, prodsViewedTagCust); return true; } catch (Exception e) { log.warn("Unable to logged-in. Force to be logged-out", e); try { kkAppEng.getCustomerMgr().logout(); } catch (KKException e1) { // do nothing } } return false; } @Override public void logOut(HttpServletRequest request, HttpServletResponse response) { try { KKAppEng kkAppEng = getKKAppEng(request); if (kkAppEng == null) { return; } KKCookieServiceImpl kkCookieServiceImpl = new KKCookieServiceImpl(); //Get recently viewed products before logging out CustomerTagIf prodsViewedTagCust = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); // Log out kkAppEng.getCustomerMgr().logout(); // Ensure that the guest customer is the one in the cookie kkCookieServiceImpl.manageCookieLogout(request, response, kkAppEng); // Set recently viewed products for the guest customer if changed while logged in CustomerTagIf prodsViewedTagGuest = kkAppEng.getCustomerTagMgr().getCustomerTag(TAG_PRODUCTS_VIEWED); updateRecentlyViewedProducts(kkAppEng, prodsViewedTagCust, prodsViewedTagGuest); } catch (KKException e) { log.error("Failed to log out from konakart", e); } catch (KKAppException e) { log.error("Failed to log out from konakart", e); } } /** * Method called when a customer logs in or logs out. When logging in we need to decide whether * to update the customer's PRODUCTS_VIEWED tag value from the value of the guest customer's * tag. When logging out we need to make the same decision in the opposite direction. We only do * the updates if the tag value of the "oldTag" is more recent than the tag value of the * "newTag". * * @param oldTag When logging in, it is the tag of the guest customer. When logging out, it is the * tag of the logged in customer. * @param newTag When logging in, it is the tag of the logged in customer. When logging out, it is * the tag of the guest customer. * @throws com.konakart.al.KKAppException . * @throws com.konakart.app.KKException . */ private void updateRecentlyViewedProducts(@Nonnull KKAppEng kkAppEng, @Nullable CustomerTagIf oldTag, @Nullable CustomerTagIf newTag) throws KKException, KKAppException { if (oldTag != null && oldTag.getDateAdded() != null && oldTag.getValue() != null && oldTag.getValue().length() > 0) { if (newTag == null || newTag.getDateAdded() == null || newTag.getDateAdded().before(oldTag.getDateAdded())) { /* * If new tag doesn't exist or old tag is newer than new tag, then give newTag the * value of old tag */ kkAppEng.getCustomerTagMgr().insertCustomerTag(TAG_PRODUCTS_VIEWED, oldTag.getValue()); } } } private Locale findPreferredLocale(HstRequestContext requestContext) { if (requestContext.getResolvedSiteMapItem() != null) { HstSiteMapItem siteMapItem = requestContext.getResolvedSiteMapItem().getHstSiteMapItem(); if (siteMapItem.getLocale() != null) { Locale locale = LocaleUtils.toLocale(siteMapItem.getLocale()); log.debug("Preferred locale for request is set to '{}' by sitemap item '{}'", siteMapItem.getLocale(), siteMapItem.getId()); return locale; } } // if we did not yet find a locale, test the Mount if (requestContext.getResolvedMount() != null) { Mount mount = requestContext.getResolvedMount().getMount(); if (mount.getLocale() != null) { Locale locale = LocaleUtils.toLocale(mount.getLocale()); log.debug("Preferred locale for request is set to '{}' by Mount '{}'", mount.getLocale(), mount.getName()); return locale; } } // no locale found return null; } }