com.bazaarvoice.seo.sdk.BVUIContentServiceProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.bazaarvoice.seo.sdk.BVUIContentServiceProvider.java

Source

/*
 * ===========================================================================
 * Copyright 2014 Bazaarvoice, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ===========================================================================
 * 
 */

package com.bazaarvoice.seo.sdk;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bazaarvoice.seo.sdk.config.BVClientConfig;
import com.bazaarvoice.seo.sdk.config.BVConfiguration;
import com.bazaarvoice.seo.sdk.exception.BVSdkException;
import com.bazaarvoice.seo.sdk.model.BVParameters;
import com.bazaarvoice.seo.sdk.url.BVSeoSdkUrl;
import com.bazaarvoice.seo.sdk.util.BVConstant;
import com.bazaarvoice.seo.sdk.util.BVMessageUtil;
import com.bazaarvoice.seo.sdk.util.BVThreadPool;
import com.bazaarvoice.seo.sdk.util.BVUtilty;

/**
 * Implementation class for {@link BVUIContentService}. This class is a self
 * executable of Callable and Future and returns StringBuilder upon execution.
 *
 * @author Anandan Narayanaswamy
 *
 */
public class BVUIContentServiceProvider implements BVUIContentService, Callable<StringBuilder> {

    private final static Logger _logger = LoggerFactory.getLogger(BVUIContentServiceProvider.class);
    private BVConfiguration _bvConfiguration;
    private BVParameters _bvParameters;
    private StringBuilder _message;
    private StringBuilder _uiContent;
    private BVSeoSdkUrl _bvSeoSdkUrl;
    private Boolean sdkEnabled;

    public BVUIContentServiceProvider(BVConfiguration bvConfiguration) {
        _bvConfiguration = bvConfiguration;

        _message = new StringBuilder();
        _uiContent = new StringBuilder();
    }

    public StringBuilder call() throws Exception {

        URI seoContentUrl = null;

        try {

            //includes integration script if one is enabled.
            includeIntegrationCode();
            seoContentUrl = _bvSeoSdkUrl.seoContentUri();
            String correctedBaseUri = _bvSeoSdkUrl.correctedBaseUri();
            getBvContent(_uiContent, seoContentUrl, correctedBaseUri);

        } catch (BVSdkException e) {

            _message.append(e.getMessage());

        }

        return _uiContent;

    }

    private void getBvContent(StringBuilder sb, URI seoContentUrl, String baseUri) {
        if (isContentFromFile()) {
            sb.append(loadContentFromFile(seoContentUrl));
        } else {
            sb.append(loadContentFromHttp(seoContentUrl));
        }

        BVUtilty.replaceString(sb, BVConstant.INCLUDE_PAGE_URI, baseUri + (baseUri.contains("?") ? "&" : "?"));
    }

    private boolean isContentFromFile() {
        boolean loadFromFile = Boolean.parseBoolean(
                _bvConfiguration.getProperty(BVClientConfig.LOAD_SEO_FILES_LOCALLY.getPropertyName()));
        return loadFromFile;
    }

    private String loadContentFromHttp(URI path) {
        int connectionTimeout = Integer
                .parseInt(_bvConfiguration.getProperty(BVClientConfig.CONNECT_TIMEOUT.getPropertyName()));
        int socketTimeout = Integer
                .parseInt(_bvConfiguration.getProperty(BVClientConfig.SOCKET_TIMEOUT.getPropertyName()));
        String proxyHost = _bvConfiguration.getProperty(BVClientConfig.PROXY_HOST.getPropertyName());
        String charsetConfig = _bvConfiguration.getProperty(BVClientConfig.CHARSET.getPropertyName());
        Charset charset = null;
        try {
            charset = charsetConfig == null ? Charset.defaultCharset() : Charset.forName(charsetConfig);
        } catch (Exception e) {
            _logger.error(BVMessageUtil.getMessage("ERR0024"));
            charset = Charset.defaultCharset();
        }

        String content = null;
        try {
            HttpURLConnection httpUrlConnection = null;
            URL url = path.toURL();

            if (!StringUtils.isBlank(proxyHost) && !"none".equalsIgnoreCase(proxyHost)) {
                int proxyPort = Integer
                        .parseInt(_bvConfiguration.getProperty(BVClientConfig.PROXY_PORT.getPropertyName()));
                SocketAddress socketAddress = new InetSocketAddress(proxyHost, proxyPort);
                Proxy proxy = new Proxy(Type.HTTP, socketAddress);
                httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
            } else {
                httpUrlConnection = (HttpURLConnection) url.openConnection();
            }

            httpUrlConnection.setConnectTimeout(connectionTimeout);
            httpUrlConnection.setReadTimeout(socketTimeout);

            InputStream is = httpUrlConnection.getInputStream();

            byte[] byteArray = IOUtils.toByteArray(is);
            is.close();

            if (byteArray == null) {
                throw new BVSdkException("ERR0025");
            }

            content = new String(byteArray, charset.name());
        } catch (MalformedURLException e) {
            //           e.printStackTrace();
        } catch (IOException e) {
            //           e.printStackTrace();
            if (e instanceof SocketTimeoutException) {
                throw new BVSdkException(e.getMessage());
            } else {
                throw new BVSdkException("ERR0012");
            }
        } catch (BVSdkException bve) {
            throw bve;
        }

        boolean isValidContent = BVUtilty.validateBVContent(content);
        if (!isValidContent) {
            throw new BVSdkException("ERR0025");
        }

        return content;
    }

    private String loadContentFromFile(URI path) {

        String content = null;
        try {
            File file = new File(path);
            content = FileUtils.readFileToString(file,
                    _bvConfiguration.getProperty(BVClientConfig.CHARSET.getPropertyName()));
        } catch (IOException e) {
            throw new BVSdkException("ERR0012");
        }

        return content;
    }

    private void includeIntegrationCode() {
        String includeScriptStr = _bvConfiguration
                .getProperty(BVClientConfig.INCLUDE_DISPLAY_INTEGRATION_CODE.getPropertyName());
        boolean includeIntegrationScript = Boolean.parseBoolean(includeScriptStr);

        if (!includeIntegrationScript) {
            return;
        }

        Object[] params = { _bvParameters.getSubjectType().uriValue(), _bvParameters.getSubjectId() };
        String integrationScriptValue = _bvConfiguration
                .getProperty(_bvParameters.getContentType().getIntegrationScriptProperty());
        String integrationScript = MessageFormat.format(integrationScriptValue, params);

        _uiContent.append(integrationScript);
    }

    public boolean showUserAgentSEOContent() {
        if (_bvParameters == null || _bvParameters.getUserAgent() == null) {
            return false;
        }

        String crawlerAgentPattern = _bvConfiguration
                .getProperty(BVClientConfig.CRAWLER_AGENT_PATTERN.getPropertyName());
        if (!StringUtils.isBlank(crawlerAgentPattern)) {
            crawlerAgentPattern = ".*(" + crawlerAgentPattern + ").*";
        }
        Pattern pattern = Pattern.compile(crawlerAgentPattern, Pattern.CASE_INSENSITIVE);
        _logger.debug("userAgent is : " + _bvParameters.getUserAgent());

        return (pattern.matcher(_bvParameters.getUserAgent()).matches()
                || _bvParameters.getUserAgent().toLowerCase().contains("google"));
    }

    public void setBVParameters(BVParameters bvParameters) {
        _bvParameters = bvParameters;
    }

    public void setBVSeoSdkUrl(BVSeoSdkUrl bvSeoSdkUrl) {
        _bvSeoSdkUrl = bvSeoSdkUrl;
    }

    public boolean isSdkEnabled() {
        if (sdkEnabled == null) {
            sdkEnabled = Boolean
                    .parseBoolean(_bvConfiguration.getProperty(BVClientConfig.SEO_SDK_ENABLED.getPropertyName()));
            sdkEnabled = sdkEnabled || _bvSeoSdkUrl.queryString().contains(BVConstant.BVREVEAL);
        }

        return sdkEnabled;
    }

    /**
     * Self executioner method.
     *
     * @param reload
     * @return
     */
    public StringBuilder executeCall(boolean reload) {
        if (reload) {
            return new StringBuilder(_uiContent);
        }

        boolean isSearchBot = showUserAgentSEOContent();
        long executionTimeout = isSearchBot
                ? Long.parseLong(
                        _bvConfiguration.getProperty(BVClientConfig.EXECUTION_TIMEOUT_BOT.getPropertyName()))
                : Long.parseLong(_bvConfiguration.getProperty(BVClientConfig.EXECUTION_TIMEOUT.getPropertyName()));

        if (!isSearchBot && executionTimeout == 0) {
            _message.append(BVMessageUtil.getMessage("MSG0004"));
            return null;
        }

        if (isSearchBot && executionTimeout < 100) {
            executionTimeout = 100;
            _message.append(BVMessageUtil.getMessage("MSG0005"));
        }

        ExecutorService executorService = BVThreadPool.getExecutorService();
        Future<StringBuilder> future = executorService.submit(this);

        try {
            _uiContent = future.get(executionTimeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            //            e.printStackTrace();
        } catch (ExecutionException e) {
            //            e.printStackTrace();
            if (e.getCause() instanceof BVSdkException) {
                throw new BVSdkException(e.getCause().getMessage());
            }
        } catch (TimeoutException e) {
            String err = isSearchBot ? "ERR0026" : "ERR0018";
            _message.append(MessageFormat.format(BVMessageUtil.getMessage(err), new Object[] { executionTimeout }));
        }

        return new StringBuilder(_uiContent);
    }

    public StringBuilder getMessage() {
        return _message;
    }
}