Search.java 12.3 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.wcm.webservicesupport.Configuration
 *  org.apache.commons.httpclient.Header
 *  org.apache.commons.httpclient.HttpClient
 *  org.apache.commons.httpclient.HttpMethod
 *  org.apache.commons.httpclient.methods.GetMethod
 *  org.apache.commons.lang3.StringEscapeUtils
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.searchpromote;

import com.day.cq.searchpromote.SearchPromoteException;
import com.day.cq.searchpromote.impl.DecompressingMethod;
import com.day.cq.searchpromote.xml.form.SearchForm;
import com.day.cq.searchpromote.xml.form.SearchFormParser;
import com.day.cq.searchpromote.xml.result.*;
import com.day.cq.wcm.webservicesupport.Configuration;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class Search {
    private final Logger log;
    public static final String VALID_QUERY_PATTERN = ".*?q\\d*=.*?";
    public static final String QUERY_PARAM_NAME = "q";
    public static final String PN_MEMBER_ID = "memberid";
    public static final String PN_ACCOUNT_NUMBER = "accountno";
    public static final String PN_SEARCHFORMXML = "searchformxml";
    private SearchFormParser searchFormParser;
    private SearchForm searchForm;
    private ResultParser resultsParser;
    private CustomerResult customerResult;
    private SlingHttpServletRequest request;
    private Configuration configuration;
    private String queryString;
    private Long requestTime;
    private Long parsingTime;

    public Search(SlingHttpServletRequest request, Configuration configuration) throws SearchPromoteException {
        this.log = LoggerFactory.getLogger(this.getClass());
        this.request = request;
        this.configuration = configuration;
        try {
            this.searchFormParser = new SearchFormParser();
            this.resultsParser = new ResultParser();
        }
        catch (Exception e) {
            this.log.error(e.getMessage(), (Throwable)e);
            throw new SearchPromoteException(e.getMessage(), e);
        }
        this.consumeRequestParameters();
        if (this.searchForm == null) {
            this.parseSearchForm();
        }
        if (this.queryString != null) {
            this.parseResults();
        }
    }

    public static String getQueryParameter(String queryString, String parameter) {
        Pattern pm;
        Matcher m;
        if (queryString != null && !"".equals(queryString) && (m = (pm = Pattern.compile(".*?" + parameter + "=([^;&/]*)?.*?")).matcher(queryString)).find()) {
            return m.group(1);
        }
        return null;
    }

    public String getQueryString() {
        return this.queryString;
    }

    public void setQueryString(String query) {
        this.queryString = query;
    }

    public SearchForm getSearchForm() {
        return this.searchForm;
    }

    public Query getQuery() {
        if (this.customerResult != null) {
            return this.customerResult.getQuery();
        }
        return null;
    }

    public List<BreadCrumbItem> getBreadcrumbs() {
        if (this.customerResult != null && this.customerResult.getBreadCrumbList() != null) {
            for (BreadCrumb b : this.customerResult.getBreadCrumbList().getItems()) {
                if (!"default".equalsIgnoreCase(b.getName())) continue;
                return b.getItems();
            }
        }
        return new ArrayList<BreadCrumbItem>();
    }

    public Pagination getPagination() {
        if (this.customerResult != null) {
            return this.customerResult.getPagination();
        }
        return null;
    }

    public List<Result> getResults() {
        if (this.customerResult != null && this.customerResult.getResultList() != null) {
            for (ResultSet rs : this.customerResult.getResultList().getResultSets()) {
                if (!"default".equalsIgnoreCase(rs.getName())) continue;
                return rs.getItems();
            }
        }
        return new ArrayList<Result>();
    }

    public String getRedirect() {
        if (this.shouldRedirect()) {
            return this.customerResult.getRedirect().getTarget();
        }
        return "";
    }

    public boolean shouldRedirect() {
        return this.customerResult != null && this.customerResult.getRedirect() != null && this.customerResult.getRedirect().getTarget() != null;
    }

    public Suggestions getSuggestion() {
        if (this.customerResult != null) {
            return this.customerResult.getSuggestions();
        }
        return null;
    }

    public List<Suggestion> getSuggestions() {
        if (this.customerResult != null && this.customerResult.getSuggestions() != null) {
            return this.customerResult.getSuggestions().getItems();
        }
        return new ArrayList<Suggestion>();
    }

    public List<Facet> getFacets() {
        if (this.customerResult != null && this.customerResult.getFacetList() != null) {
            return this.customerResult.getFacetList().getFacets();
        }
        return new ArrayList<Facet>();
    }

    public Facet getFacet(String name) {
        for (Facet facet : this.getFacets()) {
            if (!name.equals(facet.getTitle().trim())) continue;
            return facet;
        }
        return null;
    }

    public List<Banner> getBanners() {
        if (this.customerResult != null && this.customerResult.getBannerList() != null) {
            return this.customerResult.getBannerList().getBanners();
        }
        return new ArrayList<Banner>();
    }

    public Banner getBanner(String bannerArea) {
        for (Banner banner : this.getBanners()) {
            if (!banner.getArea().equals(bannerArea)) continue;
            return banner;
        }
        return null;
    }

    public List<Menu> getMenus() {
        if (this.customerResult != null && this.customerResult.getMenuList() != null) {
            return this.customerResult.getMenuList().getMenus();
        }
        return new ArrayList<Menu>();
    }

    public Menu getMenu(String menuName) {
        for (Menu menu : this.getMenus()) {
            if (!menu.getName().equals(menuName)) continue;
            return menu;
        }
        return null;
    }

    public Long getExecutionTime() {
        return this.requestTime + this.parsingTime;
    }

    private void consumeRequestParameters() {
        try {
            String q = this.request.getQueryString();
            if (this.isValidQueryString(q).booleanValue()) {
                String query = new String(q.getBytes("ISO-8859-1"), "UTF-8");
                query = this.clearQuery(query);
                this.setQueryString(query);
            }
        }
        catch (UnsupportedEncodingException e) {
            this.log.error(e.getMessage(), (Throwable)e);
        }
    }

    private void parseSearchForm() throws SearchPromoteException {
        try {
            String searchformXml = (String)this.configuration.get("searchformxml", (Object)null);
            if (searchformXml == null) {
                throw new SearchPromoteException("Search&amp;Promote configuration is missing the SearchForm XML");
            }
            this.handleXMLResponse(searchformXml);
            searchformXml = StringEscapeUtils.unescapeXml((String)searchformXml);
            this.searchForm = this.searchFormParser.parse(new InputSource(new StringReader(searchformXml)));
            this.searchForm.setRequest(this.request);
        }
        catch (Exception e) {
            this.log.error(e.getMessage(), (Throwable)e);
            throw new SearchPromoteException(e.getMessage(), e);
        }
    }

    private void parseResults() throws SearchPromoteException {
        try {
            Long startRequest = System.currentTimeMillis();
            String resultsXml = this.getResultsXML();
            this.requestTime = System.currentTimeMillis() - startRequest;
            this.log.debug(resultsXml);
            this.handleXMLResponse(resultsXml);
            Long startParse = System.currentTimeMillis();
            this.customerResult = this.resultsParser.parse(resultsXml);
            this.parsingTime = System.currentTimeMillis() - startParse;
        }
        catch (SearchPromoteException e) {
            throw e;
        }
        catch (Exception e) {
            this.log.error(e.getMessage(), (Throwable)e);
            throw new SearchPromoteException(e.getMessage(), e);
        }
    }

    private void handleXMLResponse(String responseXML) throws SearchPromoteException {
        if (responseXML == null || responseXML.contains("<html")) {
            String msg = "Search&amp;Promote returned invalid response.";
            if (responseXML != null && responseXML.contains("sp_password")) {
                msg = "Invalid log in credentials.";
            }
            this.log.error(msg);
            throw new SearchPromoteException(msg);
        }
    }

    private String getResultsXML() throws SearchPromoteException {
        if (this.searchForm == null || this.searchForm.getForm() == null) {
            throw new SearchPromoteException("Search form is not initialized");
        }
        if (this.queryString != null && !"".equals(this.queryString)) {
            return this.executeMethod(new DecompressingMethod((HttpMethod)new GetMethod(this.searchForm.getForm().getAction() + "?" + this.queryString)));
        }
        return null;
    }

    private String executeMethod(HttpMethod method) throws SearchPromoteException {
        HttpClient client = new HttpClient();
        try {
            method.setFollowRedirects(false);
            int status = client.executeMethod(method);
            if (status == 301 || status == 302 || status == 303 || status == 307) {
                Header header = method.getResponseHeader("location");
                if (header == null) {
                    String string = null;
                    return string;
                }
                String redirectUri = header.getValue();
                if (redirectUri == null || redirectUri.equals("")) {
                    String string = null;
                    return string;
                }
                String string = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?><customer-results><redirect><![CDATA[" + redirectUri + "]]></redirect></customer-results>";
                return string;
            }
            if (status != 200) {
                String header = null;
                return header;
            }
            String header = method.getResponseBodyAsString();
            return header;
        }
        catch (UnknownHostException e) {
            this.log.error(e.getMessage(), (Throwable)e);
            throw new SearchPromoteException("Unknown host: " + e.getMessage(), e);
        }
        catch (IOException e) {
            this.log.error(e.getMessage(), (Throwable)e);
            throw new SearchPromoteException(e.getMessage(), e);
        }
        finally {
            method.releaseConnection();
        }
    }

    private Boolean isValidQueryString(String query) {
        if (query != null && !"".equals(query) && query.matches(".*?q\\d*=.*?")) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private String clearQuery(String query) {
        String cleared = query;
        String delim = this.getDelimeter(query);
        if (cleared.contains("|")) {
            cleared = cleared.replaceAll("\\|", "%7C");
        }
        if (!cleared.contains("view=")) {
            cleared = cleared + delim + "view=xml";
        }
        return cleared;
    }

    private String getDelimeter(String query) {
        String delim = ";";
        if (query.indexOf("&") > -1) {
            delim = "&";
        } else if (query.indexOf("/") > -1) {
            delim = "/";
        }
        return delim;
    }
}