MobileServicesHttpClientImpl.java 12.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.crypto.CryptoSupport
 *  org.apache.commons.io.IOUtils
 *  org.apache.commons.lang3.StringUtils
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Modified
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.http.HttpEntity
 *  org.apache.http.HttpResponse
 *  org.apache.http.StatusLine
 *  org.apache.http.client.methods.HttpGet
 *  org.apache.http.client.methods.HttpUriRequest
 *  org.apache.http.impl.client.CloseableHttpClient
 *  org.apache.http.impl.client.HttpClientBuilder
 *  org.apache.http.osgi.services.HttpClientBuilderFactory
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.commons.json.JSONObject
 *  org.apache.sling.commons.osgi.PropertiesUtil
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.mobile.mobileservices.impl.service;

import com.adobe.cq.mobile.mobileservices.impl.service.MobileServicesHttpClient;
import com.adobe.cq.mobile.mobileservices.impl.util.AMSUtils;
import com.adobe.cq.mobile.platform.impl.MobileAppException;
import com.adobe.granite.crypto.CryptoSupport;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="%mobileservices.service.label", description="%mobileservices.service.description")
@Service(value={MobileServicesHttpClient.class})
@Properties(value={@Property(name="service.description", value={"Adobe Mobile Services HTTP Client"})})
public class MobileServicesHttpClientImpl
implements MobileServicesHttpClient {
    @Property(label="%mobileservices.webapi.endpoint.name", description="%mobileservices.webapi.endpoint.description", value={"https://api.omniture.com"})
    private static final String AMS_WEB_API_ENDPOINT = "ams.web.api.endpoint";
    @Property(label="%mobileservices.webapi.sdkconfig.get.operation.path.name", description="%mobileservices.webapi.sdkconfig.description", value={"/ams/1.0/app/config/"})
    private static final String GET_ADB_MOBILE_CONFIG_PATH = "get.sdk.config.path";
    @Property(label="%mobileservices.webapi.mobileserviceapps.get.operation.path.name", description="%mobileservices.webapi.mobileserviceapps.description", value={"/ams/1.0/apps"})
    private static final String GET_AMS_APPS_PATH = "get.mobileserviceapps.path";
    private String apiEndpoint;
    private String adbMobileConfigPath;
    private String getAMSAppsPath;
    @Reference
    private CryptoSupport cryptoSupportService;
    @Reference
    private HttpClientBuilderFactory httpClientBuilderFactory;
    private static final String JSON_KEY_ANALYTICS = "analytics";
    private static final String JSON_KEY_SERVER = "server";
    private static Logger logger = LoggerFactory.getLogger(MobileServicesHttpClientImpl.class);

    @Override
    public JSONObject getADBMobileConfig(String rsid, Resource resource) throws MobileAppException {
        JSONObject json = null;
        try {
            if (resource == null || ResourceUtil.isNonExistingResource((Resource)resource)) {
                String message = "The resource used to get ADB Mobile Config does not exist or is null.";
                logger.error(message);
                throw new MobileAppException(message);
            }
            Resource config = AMSUtils.getCloudServiceConfiguration(resource);
            if (config == null || ResourceUtil.isNonExistingResource((Resource)config)) {
                String message = "Could not find a Cloud Configuration from: " + resource.getPath();
                logger.error(message);
                throw new MobileAppException(message);
            }
            json = this.getAMSResponseWithConfig(this.apiEndpoint + this.adbMobileConfigPath + rsid, config);
            JSONObject data = json.getJSONObject("data");
            if (data != null) {
                json = data;
            }
            Calendar lastImported = Calendar.getInstance();
            SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss");
            json.accumulate("lastImported", (Object)sdf.format(lastImported.getTime()));
        }
        catch (Exception ex) {
            String message = "ADB Mobile Config error: " + ex.getMessage();
            logger.error(message, (Throwable)ex);
            throw new MobileAppException(message);
        }
        return json;
    }

    @Override
    public JSONObject getApps(Resource resource) throws MobileAppException {
        Resource config = AMSUtils.getCloudServiceConfiguration(resource);
        if (config == null || ResourceUtil.isNonExistingResource((Resource)config)) {
            String message = "Could not find a Cloud Configuration from: " + resource.getPath();
            logger.error(message);
            throw new MobileAppException(message);
        }
        JSONObject appListJSON = null;
        try {
            appListJSON = this.getAMSResponseWithConfig(this.apiEndpoint + this.getAMSAppsPath, config);
        }
        catch (Exception ex) {
            throw new MobileAppException(ex.getMessage());
        }
        return appListJSON;
    }

    @Override
    public JSONObject getApps(String company, String username, String secret, String server) throws MobileAppException {
        if (!server.startsWith("https")) {
            throw new MobileAppException("Cannot transfer sensitive information over non-secure URL. " + server);
        }
        if (StringUtils.isBlank((CharSequence)company) || StringUtils.isBlank((CharSequence)username) || StringUtils.isBlank((CharSequence)secret) || StringUtils.isBlank((CharSequence)server)) {
            throw new MobileAppException("Invalid account information used.");
        }
        JSONObject appListJSON = null;
        try {
            appListJSON = this.getAMSResponse(this.apiEndpoint + this.getAMSAppsPath, company, secret, username);
        }
        catch (Exception ex) {
            throw new MobileAppException(ex.getMessage());
        }
        return appListJSON;
    }

    @Override
    public String getTrackingServer(Resource mobileServiceAppResource, String rsid) throws MobileAppException {
        String trackingServer = null;
        boolean isValidFormat = false;
        try {
            JSONObject analytics;
            JSONObject adbMobileConfig = this.getADBMobileConfig(rsid, mobileServiceAppResource);
            if (adbMobileConfig != null && adbMobileConfig.has("analytics") && (analytics = adbMobileConfig.getJSONObject("analytics")).has("server")) {
                trackingServer = analytics.getString("server");
                isValidFormat = true;
            }
        }
        catch (Exception ex) {
            throw new MobileAppException(ex.getMessage());
        }
        if (!isValidFormat) {
            logger.error("Bad format on AMS Tracking Server field.  Expected 'analytics -> server' in ADB Mobile Config JSON");
        }
        return trackingServer;
    }

    private JSONObject getAMSResponseWithConfig(String URL2, Resource analyticsConfig) throws MobileAppException {
        Resource analyticsConfigContent = analyticsConfig.getChild("jcr:content");
        ValueMap vm = analyticsConfigContent.getValueMap();
        String username = (String)vm.get("username", String.class);
        String secret = (String)vm.get("secret", String.class);
        String company = (String)vm.get("company", String.class);
        return this.getAMSResponse(URL2, company, secret, username);
    }

    private JSONObject getAMSResponse(String URL2, String company, String secret, String username) {
        JSONObject responseJSON = null;
        HttpGet get = new HttpGet(URL2);
        InputStream inputStream = null;
        try {
            String usernameAuthToken = username + ":" + company;
            get.addHeader("Accept", "application/json");
            get.addHeader("Content-Type", "application/json");
            get.addHeader("x-api-client-id", "aem-mobile");
            String unprotectedSecret = secret;
            if (this.cryptoSupportService.isProtected(secret)) {
                unprotectedSecret = this.cryptoSupportService.unprotect(secret);
            }
            String wsseHeader = AMSUtils.generateWSSEHeader(usernameAuthToken, unprotectedSecret);
            get.addHeader("X-WSSE", wsseHeader);
            CloseableHttpClient httpClient = this.httpClientBuilderFactory.newBuilder().build();
            HttpResponse response = httpClient.execute((HttpUriRequest)get);
            StatusLine statusLine = response.getStatusLine();
            if (statusLine != null) {
                int status = statusLine.getStatusCode();
                if (status != 200) {
                    throw new MobileAppException("AMS Http request failed: " + response.getStatusLine().getReasonPhrase());
                }
            } else {
                throw new MobileAppException("AMS Http request failed: no status line in response.");
            }
            inputStream = response.getEntity().getContent();
            String json = IOUtils.toString((InputStream)inputStream, (String)"utf-8");
            responseJSON = new JSONObject(json);
        }
        catch (Exception ex) {
            if (ex instanceof MobileAppException) {
                throw (MobileAppException)ex;
            }
            String message = "AMS Web Api Manager error: " + ex.getMessage();
            logger.error(message, (Throwable)ex);
            throw new MobileAppException(message, ex);
        }
        finally {
            IOUtils.closeQuietly((InputStream)inputStream);
        }
        return responseJSON;
    }

    @Activate
    public void activate(Map<String, Object> properties) {
        this.modified(properties);
    }

    @Modified
    protected void modified(Map<String, Object> props) {
        this.apiEndpoint = PropertiesUtil.toString((Object)props.get("ams.web.api.endpoint"), (String)"https://api.omniture.com");
        this.adbMobileConfigPath = PropertiesUtil.toString((Object)props.get("get.sdk.config.path"), (String)"/ams/1.0/app/config/");
        this.getAMSAppsPath = PropertiesUtil.toString((Object)props.get("get.mobileserviceapps.path"), (String)"/ams/1.0/apps");
    }

    protected void bindCryptoSupportService(CryptoSupport cryptoSupport) {
        this.cryptoSupportService = cryptoSupport;
    }

    protected void unbindCryptoSupportService(CryptoSupport cryptoSupport) {
        if (this.cryptoSupportService == cryptoSupport) {
            this.cryptoSupportService = null;
        }
    }

    protected void bindHttpClientBuilderFactory(HttpClientBuilderFactory httpClientBuilderFactory) {
        this.httpClientBuilderFactory = httpClientBuilderFactory;
    }

    protected void unbindHttpClientBuilderFactory(HttpClientBuilderFactory httpClientBuilderFactory) {
        if (this.httpClientBuilderFactory == httpClientBuilderFactory) {
            this.httpClientBuilderFactory = null;
        }
    }
}