MobileClientCloudServiceMobileServicesHandler.java 19.9 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.crypto.CryptoException
 *  com.adobe.granite.crypto.CryptoSupport
 *  com.day.cq.commons.jcr.JcrUtil
 *  com.day.cq.i18n.I18n
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.api.PageManager
 *  com.day.cq.wcm.api.WCMException
 *  com.day.cq.wcm.webservicesupport.Configuration
 *  com.day.cq.wcm.webservicesupport.ConfigurationManager
 *  javax.jcr.Binary
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.Property
 *  javax.jcr.PropertyIterator
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.ValueFactory
 *  org.apache.commons.lang3.StringUtils
 *  org.apache.felix.scr.annotations.Component
 *  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.jackrabbit.commons.JcrUtils
 *  org.apache.sling.api.resource.ModifiableValueMap
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.commons.json.JSONObject
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.mobile.mobilecloudservices.impl;

import com.adobe.cq.mobile.mobilecloudservices.impl.AbstractMobileClientCloudServiceHandler;
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.CryptoException;
import com.adobe.granite.crypto.CryptoSupport;
import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.i18n.I18n;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.WCMException;
import com.day.cq.wcm.webservicesupport.Configuration;
import com.day.cq.wcm.webservicesupport.ConfigurationManager;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Map;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.Component;
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.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=0)
@Service
@Properties(value={@Property(name="cloudservice.id", value={"mobileservices"})})
public class MobileClientCloudServiceMobileServicesHandler
extends AbstractMobileClientCloudServiceHandler {
    @Reference
    MobileServicesHttpClient mobileServicesHttpClient;
    @Reference
    private CryptoSupport cryptoSupport;
    public static final String ID_AMS_CLOUD_SERVICE = "mobileservices";
    private static final String PROPERTY_AMS_COMPANY = "company";
    private static final String PROPERTY_AMS_ID = "username";
    private static final String PROPERTY_AMS_PASSWORD = "password";
    private static final String PROPERTY_SERVER = "server";
    private static final String PROPERTY_SECRET = "secret";
    private static final String PROPERTY_REPORTSUITE = "reportsuite";
    private static final String PROPERTY_REPORTSUITE_TITLE = "reportsuiteTitle";
    private static final String DEFAULT_SERVICE_PATH = "/etc/cloudservices/mobileservices";
    private static final String DEFAULT_RESOURCE_TYPE = "mobileapps/components/mobileservices";
    private static final String DEFAULT_CQ_TEMPLATE = "/libs/mobileapps/templates/mobileservices";
    private static final String DEFAULT_CONFIG_TITLE = "Provisioned Mobile Services Configuration";
    private static final String APP_DESIGNPATH = "/etc/designs/cloudservices/framework-design";
    private static final String APP_CQ_TEMPLATE = "/libs/mobileapps/templates/mobileservicesframework";
    private static final String APP_RESRC_TYPE = "mobileapps/components/mobileservicesframework";
    private String[] mandatoryProperties = new String[]{"company", "username", "password", "server", "secret", "reportsuite"};
    private final Logger logger;

    public MobileClientCloudServiceMobileServicesHandler() {
        this.logger = LoggerFactory.getLogger(this.getClass());
    }

    @Override
    public Resource createConfiguration(Map<String, Object> properties, I18n i18n, ResourceResolver resolver) throws MobileAppException {
        this.logger.debug("Creating Mobile Services Cloud Service Configuration...");
        this.checkProperties(properties, i18n);
        String pageTitle = this.getStringProperty(properties, "configName");
        if (StringUtils.isBlank((CharSequence)pageTitle)) {
            pageTitle = "Provisioned Mobile Services Configuration";
        }
        String pageName = this.getName(properties, "Provisioned Mobile Services Configuration");
        Page newConfiguration = this.createMobileServicesConfiguration(pageName, properties, pageTitle, resolver);
        Page frameworkPage = this.createMobileServicesApplication(newConfiguration, properties, resolver);
        this.saveConfigurationPublicNode((Resource)frameworkPage.adaptTo(Resource.class));
        return resolver.getResource(newConfiguration.getPath());
    }

    @Override
    public void updateConfiguration(Resource frameworkResource, Map<String, Object> properties) {
        String rsid = (String)frameworkResource.getChild("jcr:content").getValueMap().get("reportsuite", String.class);
        Resource cloudservice = frameworkResource.getParent();
        this.fetchAndSetMobileConfig(cloudservice, frameworkResource, rsid);
    }

    private void fetchAndSetMobileConfig(Resource cloudservice, Resource appPage, String reportSuite) {
        JSONObject adbMobileConfig = this.mobileServicesHttpClient.getADBMobileConfig(reportSuite, cloudservice);
        this.saveADBMobileConfig(adbMobileConfig, appPage);
    }

    @Override
    public void checkProperties(Map<String, Object> properties, I18n i18n) throws MobileAppException {
        ArrayList<String> missing = new ArrayList<String>(this.mandatoryProperties.length + 1);
        for (String nextMandatoryProperty : this.mandatoryProperties) {
            String value = this.getStringProperty(properties, nextMandatoryProperty);
            if (!StringUtils.isBlank((CharSequence)value)) continue;
            missing.add(nextMandatoryProperty);
        }
        if (!missing.isEmpty()) {
            String message = "Missing mandatory parameters: ";
            if (i18n != null) {
                message = i18n.get(message);
            }
            message = message + StringUtils.join(missing, (String)", ");
            throw new MobileAppException(message);
        }
    }

    @Override
    public String getServicePath() {
        return "/etc/cloudservices/mobileservices";
    }

    private void saveADBMobileConfig(JSONObject adbMobileConfig, Resource resource) throws MobileAppException {
        AMSUtils.verifyMobileServicesFrameworkResource(resource, true);
        try {
            Session session = (Session)resource.getResourceResolver().adaptTo(Session.class);
            ValueFactory valueFactory = session.getValueFactory();
            String str = adbMobileConfig.toString();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(str.getBytes());
            Binary binaryJson = valueFactory.createBinary((InputStream)inputStream);
            this.writeADBMobileConfig(resource.getChild("jcr:content"), binaryJson);
            if (session.hasPendingChanges()) {
                session.save();
            }
        }
        catch (Exception ex) {
            String message = "ADB Mobile Config error: " + ex.getMessage();
            this.logger.error(message, (Throwable)ex);
            throw new MobileAppException(message);
        }
    }

    @Override
    public void saveCloudConfigProperty(Resource resource, String propertyName, String configPath) throws MobileAppException {
        super.saveCloudConfigProperty(resource, propertyName, configPath);
        this.setupReports(configPath, resource.getResourceResolver(), resource);
    }

    private Page createMobileServicesConfiguration(String pageName, Map<String, Object> properties, String title, ResourceResolver resolver) throws MobileAppException {
        Page amsPage;
        PageManager pm = (PageManager)resolver.adaptTo(PageManager.class);
        I18n i18n = (I18n)resolver.adaptTo(I18n.class);
        try {
            amsPage = pm.create("/etc/cloudservices/mobileservices", pageName, "/libs/mobileapps/templates/mobileservices", title, true);
        }
        catch (WCMException wcmEx) {
            this.logger.error("Could not create Mobile Services cloud configuration: " + pageName);
            throw new MobileAppException(i18n.get("Could not create Mobile Services cloud configuration: {0}", "config name", new Object[]{pageName}));
        }
        Session session = (Session)resolver.adaptTo(Session.class);
        String userId = session.getUserID();
        Calendar now = Calendar.getInstance();
        String company = this.getStringProperty(properties, "company");
        String password = this.getStringProperty(properties, "password");
        String user = this.getStringProperty(properties, "username");
        String server = this.getStringProperty(properties, "server");
        String secret = this.getStringProperty(properties, "secret");
        ModifiableValueMap mvp = (ModifiableValueMap)amsPage.getContentResource().adaptTo(ModifiableValueMap.class);
        try {
            mvp.put((Object)"password", (Object)this.cryptoSupport.protect(password));
            mvp.put((Object)"company", (Object)company);
            mvp.put((Object)"username", (Object)user);
            mvp.put((Object)"server", (Object)server);
            mvp.put((Object)"secret", (Object)this.cryptoSupport.protect(secret));
            mvp.put((Object)"sling:resourceType", (Object)"mobileapps/components/mobileservices");
            mvp.put((Object)"jcr:lastModified", (Object)now);
            mvp.put((Object)"jcr:lastModifiedBy", (Object)userId);
            mvp.put((Object)"cq:lastModified", (Object)now);
            mvp.put((Object)"cq:lastModifiedBy", (Object)userId);
            mvp.put((Object)"cq:cloudservicename", (Object)"mobileservices");
            if (session.hasPendingChanges()) {
                session.save();
            }
        }
        catch (CryptoException cryptoEx) {
            this.logger.error("Could not set the Mobile Services cloud configuration password.");
            throw new MobileAppException(i18n.get("Could not set the Mobile Services cloud configuration password."));
        }
        catch (RepositoryException repEx) {
            this.logger.error("Error saving properties on new cloud config: " + amsPage.getPath());
            throw new MobileAppException(i18n.get("Error saving properties on new cloud config: {0}", "path to config", new Object[]{amsPage.getPath()}));
        }
        return amsPage;
    }

    private Page createMobileServicesApplication(Page newConfiguration, Map<String, Object> properties, ResourceResolver resolver) {
        Page applicationPage;
        PageManager pm = (PageManager)resolver.adaptTo(PageManager.class);
        I18n i18n = (I18n)resolver.adaptTo(I18n.class);
        String reportSuite = this.getStringProperty(properties, "reportsuite");
        String reportSuites = reportSuite + ";";
        String reportSuiteTitle = this.getStringProperty(properties, "reportsuiteTitle");
        if (StringUtils.isBlank((CharSequence)reportSuiteTitle)) {
            reportSuiteTitle = reportSuite;
        }
        try {
            applicationPage = pm.create(newConfiguration.getPath(), JcrUtil.createValidName((String)reportSuiteTitle), "/libs/mobileapps/templates/mobileservicesframework", reportSuiteTitle, true);
        }
        catch (WCMException wcmEx) {
            this.logger.error("Could not create Mobile Services Application page: " + reportSuiteTitle);
            throw new MobileAppException(i18n.get("Could not create Mobile Services Application page: {0}", "config name", new Object[]{reportSuiteTitle}));
        }
        Session session = (Session)resolver.adaptTo(Session.class);
        String userId = session.getUserID();
        Calendar now = Calendar.getInstance();
        Resource content = applicationPage.getContentResource();
        ModifiableValueMap mvp = (ModifiableValueMap)content.adaptTo(ModifiableValueMap.class);
        try {
            String trackingServer;
            mvp.put((Object)"cq:designPath", (Object)"/etc/designs/cloudservices/framework-design");
            mvp.put((Object)"reportsuite", (Object)reportSuite);
            mvp.put((Object)"reportsuites", (Object)reportSuites);
            mvp.put((Object)"sling:resourceType", (Object)"mobileapps/components/mobileservicesframework");
            mvp.put((Object)"jcr:lastModified", (Object)now);
            mvp.put((Object)"jcr:lastModifiedBy", (Object)userId);
            mvp.put((Object)"cq:lastModified", (Object)now);
            mvp.put((Object)"cq:lastModifiedBy", (Object)userId);
            if (session.hasPendingChanges()) {
                session.save();
            }
            if (StringUtils.isNotBlank((CharSequence)(trackingServer = this.mobileServicesHttpClient.getTrackingServer(applicationPage.getContentResource().getParent(), reportSuite)))) {
                mvp.put((Object)"cq:trackingServer", (Object)trackingServer);
                if (session.hasPendingChanges()) {
                    session.save();
                }
            }
        }
        catch (RepositoryException repEx) {
            this.logger.error("Error saving properties on new cloud config: " + applicationPage.getPath());
            throw new MobileAppException(i18n.get("Error saving properties on new cloud config: {0}", "path to config", new Object[]{applicationPage.getPath()}));
        }
        try {
            Resource mappings = ResourceUtil.getOrCreateResource((ResourceResolver)resolver, (String)(applicationPage.getPath() + "/jcr:content/mappings"), (String)"nt:unstructured", (String)"", (boolean)true);
            mvp = (ModifiableValueMap)mappings.adaptTo(ModifiableValueMap.class);
            mvp.put((Object)"sling:resourceType", (Object)"cq/analytics/components/mappings/maparsys");
            if (session.hasPendingChanges()) {
                session.save();
            }
        }
        catch (Exception ex) {
            this.logger.error("Could not create Mobile Services Application page's mappings node.");
            throw new MobileAppException(i18n.get("Could not create Mobile Services Application page's mappings node."), ex);
        }
        return applicationPage;
    }

    private void writeADBMobileConfig(Resource analyticsAppFramework, Binary jsonContent) throws MobileAppException {
        try {
            Session session = (Session)analyticsAppFramework.getResourceResolver().adaptTo(Session.class);
            Node adbMobileConfig = this.getOrCreateMobileConfig(analyticsAppFramework, session);
            adbMobileConfig.setProperty("jcr:mimeType", "application/json");
            adbMobileConfig.setProperty("jcr:data", jsonContent);
            Calendar lastImported = Calendar.getInstance();
            adbMobileConfig.setProperty("jcr:lastModified", lastImported);
            if (session.hasPendingChanges()) {
                session.save();
            }
        }
        catch (Exception ex) {
            throw new MobileAppException(ex.getMessage(), ex);
        }
    }

    private Node getOrCreateMobileConfig(Resource analyticsAppFramework, Session session) throws MobileAppException {
        String path = analyticsAppFramework.getPath() + "/" + "adbmobileconfig";
        ResourceResolver resolver = analyticsAppFramework.getResourceResolver();
        Node adbMobileConfig = null;
        try {
            adbMobileConfig = !session.nodeExists(path) ? JcrUtils.getOrCreateByPath((String)path, (String)"nt:resource", (Session)session) : JcrUtils.getNodeIfExists((String)path, (Session)session);
        }
        catch (Exception ex) {
            throw new MobileAppException(ex.getMessage(), ex);
        }
        return adbMobileConfig;
    }

    private void setupReports(String configPath, ResourceResolver resolver, Resource appInstance) throws MobileAppException {
        Resource appContent = appInstance.getChild("jcr:content");
        String appContentPath = appContent.getPath();
        ConfigurationManager configurationManager = (ConfigurationManager)resolver.adaptTo(ConfigurationManager.class);
        Configuration configuration = configurationManager.getConfiguration(configPath);
        String reportId = AMSUtils.getReportSuites(configuration);
        try {
            Node reports;
            Session session = (Session)resolver.adaptTo(Session.class);
            Node src = session.getNode("/libs/mobileapps/admin/content/dashboard/tiles/default/appmetrics/jcr:content/reports");
            String destPath = appContentPath + "/" + "reports" + "/" + reportId;
            if (!session.nodeExists(destPath)) {
                Node reportNode = JcrUtil.createPath((String)destPath, (String)"nt:unstructured", (Session)session);
                reports = JcrUtil.copy((Node)src, (Node)reportNode, (String)null);
            } else {
                reports = session.getNode(destPath);
                this.cleanReports(reports);
            }
            this.updateDataStore(reports, reportId);
            resolver.commit();
        }
        catch (Exception e) {
            String statusMsg = "Unable to update the mobile services config for app instance: " + appInstance.getPath();
            this.logger.error(statusMsg);
            throw new MobileAppException(statusMsg, e);
        }
    }

    private void cleanReports(Node reports) throws RepositoryException {
        Node reportNode = reports.getNode("reports");
        NodeIterator nodes = reportNode.getNodes();
        while (nodes.hasNext()) {
            Node childNode = (Node)nodes.next();
            if (!childNode.hasProperty("cq:lastAttempt")) continue;
            javax.jcr.Property property = childNode.getProperty("cq:lastAttempt");
            property.remove();
        }
    }

    private void updateDataStore(Node node, String reportId) throws RepositoryException {
        PropertyIterator dataStoreIterator = node.getProperties("data_store");
        while (dataStoreIterator.hasNext()) {
            javax.jcr.Property property = (javax.jcr.Property)dataStoreIterator.next();
            property.setValue("dms/" + reportId);
        }
        NodeIterator nodes = node.getNodes();
        while (nodes.hasNext()) {
            Node childNode = (Node)nodes.next();
            this.updateDataStore(childNode, reportId);
        }
    }

    protected void bindMobileServicesHttpClient(MobileServicesHttpClient mobileServicesHttpClient) {
        this.mobileServicesHttpClient = mobileServicesHttpClient;
    }

    protected void unbindMobileServicesHttpClient(MobileServicesHttpClient mobileServicesHttpClient) {
        if (this.mobileServicesHttpClient == mobileServicesHttpClient) {
            this.mobileServicesHttpClient = null;
        }
    }

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

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