PGBuildManagerImpl.java 20 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.inherit.InheritanceValueMap
 *  com.day.cq.contentsync.ContentSyncManager
 *  com.day.cq.wcm.api.Page
 *  com.day.cq.wcm.webservicesupport.Configuration
 *  com.day.cq.wcm.webservicesupport.ConfigurationManager
 *  javax.jcr.Item
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.commons.io.IOUtils
 *  org.apache.http.entity.mime.content.ContentBody
 *  org.apache.http.entity.mime.content.FileBody
 *  org.apache.http.impl.client.HttpClientBuilder
 *  org.apache.http.osgi.services.HttpClientBuilderFactory
 *  org.apache.sling.api.adapter.AdapterManager
 *  org.apache.sling.api.resource.ModifiableValueMap
 *  org.apache.sling.api.resource.PersistenceException
 *  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.phonegap.impl.build.service;

import com.adobe.cq.mobile.phonegap.impl.PGBuildException;
import com.adobe.cq.mobile.phonegap.impl.PGException;
import com.adobe.cq.mobile.phonegap.impl.build.PGBRequest;
import com.adobe.cq.mobile.phonegap.impl.build.PGBuildManager;
import com.adobe.cq.mobile.phonegap.impl.build.PGBuildUserAccount;
import com.adobe.cq.mobile.phonegap.impl.build.action.PostAppBuild;
import com.adobe.cq.mobile.phonegap.impl.build.metadata.AccountInfo;
import com.adobe.cq.mobile.phonegap.impl.build.metadata.AppInfo;
import com.adobe.cq.mobile.phonegap.impl.build.util.RestClientUtil;
import com.adobe.granite.crypto.CryptoException;
import com.adobe.granite.crypto.CryptoSupport;
import com.day.cq.commons.inherit.InheritanceValueMap;
import com.day.cq.contentsync.ContentSyncManager;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.webservicesupport.Configuration;
import com.day.cq.wcm.webservicesupport.ConfigurationManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.io.IOUtils;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.adapter.AdapterManager;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
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;

public class PGBuildManagerImpl
implements PGBuildManager {
    private static String phonegapBuildHost = "build.phonegap.com";
    private static int phonegapBuildPort = 443;
    private static final Logger LOGGER = LoggerFactory.getLogger(PGBuildManagerImpl.class);
    private static final String PGBUILD_SERVICE_NAME = "phonegap-build";
    private final boolean useSsl;
    private Session userSession = null;
    private ConfigurationManager configurationManagerService = null;
    private ContentSyncManager contentSyncManagerService = null;
    private AdapterManager adapterManagerService = null;
    private CryptoSupport cryptoSupportService = null;
    private HttpClientBuilderFactory clientBuilderFactory = null;

    public PGBuildManagerImpl(Session userSession, ContentSyncManager contentSyncManagerService, AdapterManager adapterManagerService, ConfigurationManager configurationManagerService, CryptoSupport cryptoSupportService, HttpClientBuilderFactory clientBuilderFactory, int port, String host, boolean useSsl) {
        this.userSession = userSession;
        this.contentSyncManagerService = contentSyncManagerService;
        this.adapterManagerService = adapterManagerService;
        this.configurationManagerService = configurationManagerService;
        this.cryptoSupportService = cryptoSupportService;
        this.clientBuilderFactory = clientBuilderFactory;
        phonegapBuildPort = port;
        phonegapBuildHost = host;
        this.useSsl = useSsl;
    }

    public PGBuildUserAccount getPGAccountInfo(Page phoneGapBuildEnabledPage) throws RepositoryException, CryptoException, PGException {
        Configuration pgBuildConfiguration = this.getPGBuildAccountConfiguration(phoneGapBuildEnabledPage);
        if (pgBuildConfiguration == null) {
            throw new PGException("PGBuild CloudService configuration not found or target does not exist on: " + phoneGapBuildEnabledPage.getPath());
        }
        InheritanceValueMap cmap = pgBuildConfiguration.getProperties();
        String userId = (String)cmap.get("pgBuildUserId", String.class);
        String password = (String)cmap.get("pgBuildPassword", String.class);
        if (this.cryptoSupportService != null && this.cryptoSupportService.isProtected(password)) {
            password = this.cryptoSupportService.unprotect(password);
        }
        if (userId == null || password == null) {
            throw new PGException("PGBuild CloudService configuration invalid. Account credentials not set for configuration: " + pgBuildConfiguration.getName());
        }
        return new PGBuildUserAccount(userId, password);
    }

    public Configuration getPGBuildAccountConfiguration(Page phoneGapBuildEnabledPage) throws RepositoryException {
        Configuration pgConfig = null;
        try {
            String[] cloudServiceConfigPaths = (String[])phoneGapBuildEnabledPage.getProperties().get("cq:cloudserviceconfigs", String[].class);
            if (cloudServiceConfigPaths != null) {
                pgConfig = this.configurationManagerService.getConfiguration("phonegap-build", cloudServiceConfigPaths);
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Failed to get PGBuild account configuration", (Throwable)ex);
        }
        return pgConfig;
    }

    @Override
    public AppInfo createApp(Page phoneGapBuildEnabledPage) throws PGException {
        AppInfo appInfo = null;
        try {
            LOGGER.debug("Creating PhoneGap Build app for {} ", (Object)phoneGapBuildEnabledPage.getPath());
            Page thePhoneGapRootPage = this.getPhoneGapBuildRootPage(phoneGapBuildEnabledPage);
            if (null == thePhoneGapRootPage) {
                throw new PGException("PhoneGap config not found in ancestry of  " + (Object)thePhoneGapRootPage);
            }
            PGBuildUserAccount pgBuildUserAccount = this.getPGAccountInfo(thePhoneGapRootPage);
            appInfo = this.initiateBuild(this.userSession, pgBuildUserAccount, thePhoneGapRootPage, null);
            LOGGER.debug("App created and build initiated {} ", (Object)appInfo);
        }
        catch (Exception ex) {
            throw new PGException("Failed to create app for " + phoneGapBuildEnabledPage.getPath(), ex);
        }
        return appInfo;
    }

    @Override
    public AppInfo updateApp(Page phoneGapBuildEnabledPage) throws PGException {
        AppInfo appInfo = null;
        try {
            LOGGER.debug("Updating PhoneGap Build app for {} ", (Object)phoneGapBuildEnabledPage.getPath());
            Page thePhoneGapRootPage = this.getPhoneGapBuildRootPage(phoneGapBuildEnabledPage);
            if (null == thePhoneGapRootPage) {
                throw new PGException("PhoneGap config not found in ancestry of  " + (Object)thePhoneGapRootPage);
            }
            PGBuildUserAccount pgBuildUserAccount = this.getPGAccountInfo(thePhoneGapRootPage);
            String buildId = this.getPhoneGapBuildId(thePhoneGapRootPage);
            appInfo = this.initiateBuild(this.userSession, pgBuildUserAccount, thePhoneGapRootPage, buildId);
            LOGGER.debug("App updated and build initiated {} ", (Object)appInfo);
        }
        catch (Exception ex) {
            throw new PGException("Failed update app for " + phoneGapBuildEnabledPage.getPath(), ex);
        }
        return appInfo;
    }

    @Override
    public AppInfo getApp(Page phoneGapBuildEnabledPage) throws PGException {
        AppInfo appInfo = null;
        try {
            LOGGER.debug("Get PhoneGap Build app for {}", (Object)phoneGapBuildEnabledPage.getPath());
            String appID = this.getPhoneGapBuildId(phoneGapBuildEnabledPage);
            if (appID != null) {
                PGBuildUserAccount pgBuildUserAccount = this.getPGAccountInfo(phoneGapBuildEnabledPage);
                PGBRequest request = new PGBRequest(this.clientBuilderFactory.newBuilder(), phonegapBuildHost, phonegapBuildPort, pgBuildUserAccount, this.useSsl);
                JSONObject response = RestClientUtil.submitGetRequest(request, request.getAppURL(appID));
                appInfo = new AppInfo(response);
            }
        }
        catch (PGBuildException pgBuildEx) {
            ModifiableValueMap modifiableValueMap;
            String buildId;
            Resource contentRes;
            if (pgBuildEx.getErrorCode() == 404 && pgBuildEx.getErrorDetails().matches("app \\d+ not found") && (buildId = (String)(modifiableValueMap = (ModifiableValueMap)(contentRes = phoneGapBuildEnabledPage.getContentResource()).adaptTo(ModifiableValueMap.class)).get("phonegap-buildId", String.class)) != null) {
                modifiableValueMap.remove((Object)"phonegap-buildId");
                modifiableValueMap.remove((Object)"phonegap-builtBy");
                try {
                    contentRes.getResourceResolver().commit();
                }
                catch (PersistenceException perEx) {
                    throw new PGException("Failed to clear bad app id for " + phoneGapBuildEnabledPage.getPath(), (Throwable)perEx);
                }
                LOGGER.info("Build ID " + buildId + " was removed from the app because it does not exist on the PhoneGap Build server.  Affected " + phoneGapBuildEnabledPage.getPath());
                throw new PGException("Build id '" + buildId + "' does not exist and was deleted.", pgBuildEx);
            }
            throw new PGException("Failed to get app for " + phoneGapBuildEnabledPage.getPath(), pgBuildEx);
        }
        catch (Exception ex) {
            throw new PGException("Failed to get app for " + phoneGapBuildEnabledPage.getPath(), ex);
        }
        return appInfo;
    }

    @Override
    public AccountInfo getAccountProfile(Page phoneGapBuildEnabledPage) throws PGException {
        AccountInfo accInfo = null;
        try {
            LOGGER.debug("Get PhoneGap Build account profile for {}", (Object)phoneGapBuildEnabledPage.getPath());
            PGBuildUserAccount pgBuildUserAccount = this.getPGAccountInfo(phoneGapBuildEnabledPage);
            PGBRequest request = new PGBRequest(this.clientBuilderFactory.newBuilder(), phonegapBuildHost, phonegapBuildPort, pgBuildUserAccount, this.useSsl);
            JSONObject response = RestClientUtil.submitGetRequest(request, request.getAccountProfileURL());
            accInfo = new AccountInfo(response);
        }
        catch (PGException pbEx) {
            throw pbEx;
        }
        catch (Exception ex) {
            throw new PGException("Failed to get account profile for " + phoneGapBuildEnabledPage.getPath(), ex);
        }
        return accInfo;
    }

    @Override
    public AccountInfo getAccountProfile(String userId, String password) throws PGException {
        AccountInfo accInfo = null;
        try {
            LOGGER.debug("Get PhoneGap Build account profile for {}", (Object)userId);
            if (this.cryptoSupportService != null && this.cryptoSupportService.isProtected(password)) {
                password = this.cryptoSupportService.unprotect(password);
            }
            PGBuildUserAccount pgBuildUserAccount = new PGBuildUserAccount(userId, password);
            PGBRequest request = new PGBRequest(this.clientBuilderFactory.newBuilder(), phonegapBuildHost, phonegapBuildPort, pgBuildUserAccount, this.useSsl);
            JSONObject response = RestClientUtil.submitGetRequest(request, request.getAccountProfileURL());
            accInfo = new AccountInfo(response);
        }
        catch (Exception ex) {
            throw new PGException("Failed to get account profile for " + userId, ex);
        }
        return accInfo;
    }

    private String getContentSyncConfigPath(Page page) {
        String contentSyncConfigPath = null;
        String propertyKey = "phonegap-build-exportTemplate";
        if (page.getProperties().containsKey((Object)propertyKey)) {
            contentSyncConfigPath = (String)page.getProperties().get(propertyKey, String.class);
        } else {
            propertyKey = "phonegap-exportTemplate";
            if (page.getProperties().containsKey((Object)propertyKey)) {
                contentSyncConfigPath = (String)page.getProperties().get(propertyKey, String.class);
            }
        }
        if (contentSyncConfigPath.startsWith(".")) {
            contentSyncConfigPath = page.getContentResource().getPath() + "/" + contentSyncConfigPath;
            contentSyncConfigPath = ResourceUtil.normalize((String)contentSyncConfigPath);
        }
        return contentSyncConfigPath;
    }

    private Page getPhoneGapBuildRootPage(Page currentPage) throws Exception {
        Page thePhoneGapRootPage = null;
        if (this.getContentSyncConfigPath(currentPage) != null) {
            thePhoneGapRootPage = currentPage;
        } else if (currentPage.getParent() != null) {
            thePhoneGapRootPage = this.getSiteNodeWithPhoneGapRef(currentPage.getParent());
        }
        return thePhoneGapRootPage;
    }

    private Page getSiteNodeWithPhoneGapRef(Page currentPage) throws RepositoryException {
        if (currentPage.getDepth() == 0) {
            return null;
        }
        if (this.getContentSyncConfigPath(currentPage) != null) {
            return currentPage;
        }
        return this.getSiteNodeWithPhoneGapRef(currentPage.getParent());
    }

    /*
     * Enabled force condition propagation
     * Lifted jumps to return sites
     */
    private AppInfo initiateBuild(Session jcrSession, PGBuildUserAccount getPGAccountInfo, Page thePhoneGapRootPage, String buildId) throws RepositoryException, PGException, Exception {
        PGBRequest request;
        AppInfo appInfo = null;
        if (thePhoneGapRootPage == null) throw new PGException("PhoneGap config not found at " + (Object)thePhoneGapRootPage);
        if (this.getContentSyncConfigPath(thePhoneGapRootPage) == null) throw new PGException("Export config property not found on  " + (Object)thePhoneGapRootPage);
        ContentBody buildContentStreamSource = this.getBuildContentAsStreamPartSource(thePhoneGapRootPage);
        String title = this.getTitle(thePhoneGapRootPage);
        Resource res = thePhoneGapRootPage.getContentResource();
        Node thePhoneGapRootNode = (Node)res.adaptTo(Node.class);
        if (null == buildId) {
            request = new PGBRequest(this.clientBuilderFactory.newBuilder(), phonegapBuildHost, phonegapBuildPort, getPGAccountInfo, this.useSsl);
            PostAppBuild build = new PostAppBuild();
            appInfo = build.createAppBuild(request, buildContentStreamSource, title);
            buildId = appInfo.getId();
            thePhoneGapRootNode.setProperty("phonegap-buildId", buildId);
        } else {
            request = new PGBRequest(this.clientBuilderFactory.newBuilder(), phonegapBuildHost, phonegapBuildPort, getPGAccountInfo, this.useSsl);
            PostAppBuild build = new PostAppBuild();
            appInfo = build.updateAppBuild(request, buildId, buildContentStreamSource, title);
        }
        LOGGER.debug(String.valueOf(appInfo));
        thePhoneGapRootNode.setProperty("phonegap-lastBuilt", Calendar.getInstance());
        thePhoneGapRootNode.setProperty("phonegap-builtBy", jcrSession.getUserID());
        jcrSession.save();
        if (!(buildContentStreamSource instanceof FileBody)) return appInfo;
        File file = ((FileBody)buildContentStreamSource).getFile();
        file.delete();
        return appInfo;
    }

    private ContentBody getBuildContentAsStreamPartSource(Page thePhoneGapRootPage) throws RepositoryException, PGException {
        FileBody buildFileContentBody;
        block5 : {
            buildFileContentBody = null;
            try {
                String contentSyncConfigPath = this.getContentSyncConfigPath(thePhoneGapRootPage);
                if (contentSyncConfigPath != null) {
                    Resource configResource = thePhoneGapRootPage.getContentResource().getResourceResolver().getResource(contentSyncConfigPath);
                    if (configResource.isResourceType("contentsync/config")) {
                        buildFileContentBody = new FileBody(this.getContentSyncContentAsFile(configResource));
                        break block5;
                    }
                    throw new PGException("Resource referenced at " + contentSyncConfigPath + " is not of type: " + "contentsync/config");
                }
                throw new PGException("Export template not set: " + (Object)thePhoneGapRootPage);
            }
            catch (PGException ex) {
                throw ex;
            }
            catch (Exception ex) {
                throw new PGException("Failed to get build content using " + (Object)thePhoneGapRootPage, ex);
            }
        }
        return buildFileContentBody;
    }

    private String getTitle(Page thePhoneGapRootPage) throws RepositoryException {
        return (String)thePhoneGapRootPage.getProperties().get("phonegap-title", (Object)thePhoneGapRootPage.getName());
    }

    private String getPhoneGapBuildId(Page thePhoneGapRootPage) {
        String buildId = null;
        if (thePhoneGapRootPage.getProperties().containsKey((Object)"phonegap-buildId")) {
            buildId = (String)thePhoneGapRootPage.getProperties().get("phonegap-buildId", String.class);
        }
        return buildId;
    }

    public File getContentSyncContentAsFile(Resource configResource) throws Exception {
        File file;
        block5 : {
            file = null;
            try {
                Session session = this.userSession;
                this.contentSyncManagerService.updateCache(configResource, session);
                String zipPath = this.contentSyncManagerService.getZip(configResource, null, session);
                Node zipNode = null;
                try {
                    zipNode = (Node)session.getItem(zipPath);
                }
                catch (RepositoryException ex) {
                    zipNode = (Node)session.getItem("/var/contentsync" + zipPath);
                }
                Node contentNode = zipNode.getNode("jcr:content");
                if (contentNode.isNodeType("nt:resource")) {
                    Property property = contentNode.getProperty("jcr:data");
                    file = File.createTempFile("cq" + this.getClass().getSimpleName(), ".zip");
                    InputStream in = property.getStream();
                    FileOutputStream out = new FileOutputStream(file);
                    IOUtils.copy((InputStream)in, (OutputStream)out);
                    in.close();
                    out.close();
                    break block5;
                }
                throw new PGException("Node " + (Object)contentNode + " is not of type: " + "nt:resource");
            }
            catch (Exception ex) {
                throw new PGException("Failed to get ContentSync zip for config " + (Object)configResource, ex);
            }
        }
        return file;
    }

    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
        if (Session.class == type) {
            return (AdapterType)this.userSession;
        }
        return null;
    }
}