Msm54RolloutConfigUpgrade.java 10.1 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.jcr.JcrUtil
 *  javax.jcr.Item
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Workspace
 *  javax.jcr.query.Query
 *  javax.jcr.query.QueryManager
 *  javax.jcr.query.QueryResult
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.compat.codeupgrade.impl.cq54;

import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.compat.codeupgrade.internal.api.ProgressInfoProvider;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Msm54RolloutConfigUpgrade
implements ProgressInfoProvider {
    private final Logger log;
    static final String CQ_LIVE_SYNC_ACTION_NAME = "cq:LiveSyncAction";
    static final String CQ_ROLLOUT_CONFIG_ID_53 = "cq:rolloutConfigId53";
    static final String ROLLOUT_CONFIG_RESOURCE_TYPE = "wcm/msm/components/rolloutconfig";
    static final String ROLLOUT_CONFIGS_PATH = "/etc/msm/rolloutconfigs";
    static final String NEW_CONFIGS_NODE_NAME = "53upgrade";
    static final String NEW_CONFIGS_PATH = "/etc/msm/rolloutconfigs/53upgrade";
    private final String BACKUP_ROOT;
    static final String PROP_UPDATE_CONTENT_STATUS = "updateContent/status";
    static final String PROP_NOTIFY_TARGET = "notify/target";
    static final String PROP_MANDATORY_TARGET = "mandatory/target";
    static final String PROP_WORKFLOW_TARGET = "workflow/target";
    int newConfigNumber;
    int ignoredCount;
    int upgradedCount;
    private String progressInfo;

    Msm54RolloutConfigUpgrade() {
        this.log = LoggerFactory.getLogger(this.getClass());
        this.BACKUP_ROOT = "/var/upgrade/" + this.getClass().getSimpleName() + "/backup/" + Msm54RolloutConfigUpgrade.getBackupNodeName();
    }

    @Override
    public String getProgressInfo() {
        return this.progressInfo;
    }

    void setProgressInfo(String info) {
        this.progressInfo = info;
        this.log.info(this.progressInfo);
    }

    void doUpgrade(Session s) throws Exception {
        String statement = "select * from [cq:LiveSyncConfig]";
        this.setProgressInfo("Searching for nodes to upgrade");
        this.log.info("Executing query '{}' to find nodes to upgrade", (Object)"select * from [cq:LiveSyncConfig]");
        NodeIterator it = s.getWorkspace().getQueryManager().createQuery("select * from [cq:LiveSyncConfig]", "JCR-SQL2").execute().getNodes();
        int counter = 0;
        while (it.hasNext()) {
            this.setProgressInfo("" + counter + " nodes checked, " + this.upgradedCount + " upgraded");
            ++counter;
            ConfigNodesPair cnp = new ConfigNodesPair(it.nextNode());
            if (!cnp.needsUpgrade()) {
                ++this.ignoredCount;
                this.log.info("Rollout config does not need upgrading, not modified: {}", (Object)cnp.getMainPath());
                continue;
            }
            ++this.upgradedCount;
            this.upgrade(s, cnp);
        }
        this.setProgressInfo("Done executing upgrades, " + this.upgradedCount + " config nodes upgraded, " + this.ignoredCount + " nodes ignored");
    }

    private void upgrade(Session s, ConfigNodesPair cnp) throws RepositoryException {
        String configId = this.getConfigId(cnp);
        this.log.info("Upgrading rollout config {} (Id={})", (Object)cnp.getMainPath(), (Object)configId);
        String cfgPath = this.findConfigPath(s, configId);
        boolean created = false;
        if (cfgPath == null) {
            created = true;
            cfgPath = this.createConfig(s, configId);
        }
        cnp.configNode.setProperty("cq:rolloutConfigs", new String[]{cfgPath});
        cnp.configNode.getProperty("cq:trigger").remove();
        Object[] arrobject = new Object[3];
        arrobject[0] = created ? "newly created" : "existing";
        arrobject[1] = cfgPath;
        arrobject[2] = cnp.configNode.getPath();
        this.log.info("Rollout config node upgraded, using {} config {} for {}", arrobject);
        String srcPath = cnp.actionNode.getPath();
        String backupPath = this.BACKUP_ROOT + srcPath;
        String backupFolder = this.BACKUP_ROOT + cnp.actionNode.getParent().getPath();
        JcrUtil.createPath((String)backupFolder, (String)"nt:unstructured", (Session)s);
        s.save();
        s.getWorkspace().move(srcPath, backupPath);
        this.log.info("Unused rollout config node {} moved to {}", (Object)srcPath, (Object)backupPath);
    }

    String getIdString(Node n, String propertyPath) throws RepositoryException {
        if (n.hasProperty(propertyPath)) {
            return propertyPath + "=" + n.getProperty(propertyPath).getString() + "#";
        }
        return "#";
    }

    String getConfigId(ConfigNodesPair cnp) throws RepositoryException {
        StringBuilder sb = new StringBuilder();
        sb.append(this.getIdString(cnp.configNode, "cq:trigger"));
        sb.append(this.getIdString(cnp.actionNode, "updateContent/status"));
        sb.append(this.getIdString(cnp.actionNode, "notify/target"));
        sb.append(this.getIdString(cnp.actionNode, "mandatory/target"));
        sb.append(this.getIdString(cnp.actionNode, "workflow/target"));
        return sb.toString();
    }

    String findConfigPath(Session s, String configId) throws RepositoryException {
        String result = null;
        String statement = "SELECT * FROM 'nt:base' WHERE [sling:resourceType]='wcm/msm/components/rolloutconfig' AND [cq:rolloutConfigId53]='" + configId + "'" + " AND ISDESCENDANTNODE([" + "/etc/msm/rolloutconfigs" + "])";
        NodeIterator it = s.getWorkspace().getQueryManager().createQuery(statement, "JCR-SQL2").execute().getNodes();
        if (it.hasNext()) {
            result = it.nextNode().getParent().getPath();
            if (it.hasNext()) {
                throw new RepositoryException("More than one node found for query " + statement);
            }
        }
        return result;
    }

    Map<String, String> parseConfigId(String configId) {
        String[] parts;
        HashMap<String, String> result = new HashMap<String, String>();
        for (String part : parts = configId.split("#")) {
            String[] pair = part.split("=");
            if (pair.length != 2) continue;
            result.put(pair[0], pair[1]);
        }
        return result;
    }

    Node getActionNode(Node content, String childName) throws RepositoryException {
        Node n = null;
        n = content.hasNode(childName) ? content.getNode(childName) : content.addNode(childName, "cq:LiveSyncAction");
        return n;
    }

    String createConfig(Session s, String configId) throws RepositoryException {
        Node base = null;
        if (s.itemExists("/etc/msm/rolloutconfigs/53upgrade")) {
            base = (Node)s.getItem("/etc/msm/rolloutconfigs/53upgrade");
        } else {
            base = s.getNode("/etc/msm/rolloutconfigs").addNode("53upgrade", "sling:Folder");
            s.save();
        }
        Node cfgNode = base.addNode("" + ++this.newConfigNumber + "_53upgrade_" + System.currentTimeMillis(), "cq:Page");
        Node content = cfgNode.addNode("jcr:content", "nt:unstructured");
        content.setProperty("sling:resourceType", "wcm/msm/components/rolloutconfig");
        content.setProperty("cq:defaultView", "html");
        content.setProperty("cq:lastModified", Calendar.getInstance());
        content.setProperty("cq:lastModifiedBy", s.getUserID());
        content.setProperty("cq:template", "/libs/wcm/msm/templates/rolloutconfig");
        content.setProperty("jcr:title", cfgNode.getName());
        content.setProperty("jcr:description", "Compatibility rollout config created by " + this.getClass().getSimpleName());
        Map<String, String> cfgMap = this.parseConfigId(configId);
        content.setProperty("cq:trigger", cfgMap.get("cq:trigger"));
        if ("true".equals(cfgMap.get("updateContent/status"))) {
            this.getActionNode(content, "contentUpdate").setProperty("enabled", true);
            this.getActionNode(content, "contentCopy").setProperty("enabled", true);
            this.getActionNode(content, "contentDelete").setProperty("enabled", true);
            this.getActionNode(content, "referencesUpdate").setProperty("enabled", true);
            this.getActionNode(content, "orderChildren").setProperty("enabled", true);
        }
        if ("true".equals(cfgMap.get("notify/target"))) {
            this.getActionNode(content, "notify").setProperty("enabled", true);
        }
        if (cfgMap.get("mandatory/target") != null) {
            this.getActionNode(content, "mandatory").setProperty("target", cfgMap.get("mandatory/target"));
        }
        if (cfgMap.get("workflow/target") != null) {
            this.getActionNode(content, "workflow").setProperty("target", cfgMap.get("workflow/target"));
        }
        content.setProperty("cq:rolloutConfigId53", configId);
        s.save();
        return cfgNode.getPath();
    }

    static String getBackupNodeName() {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-S");
        return fmt.format(new Date());
    }

    static class ConfigNodesPair {
        final Node configNode;
        final Node actionNode;

        ConfigNodesPair(Node liveSyncConfigNode) throws RepositoryException {
            this.configNode = liveSyncConfigNode;
            Node parent = this.configNode.getParent();
            this.actionNode = parent.hasNode("cq:LiveSyncAction") ? parent.getNode("cq:LiveSyncAction") : null;
        }

        String getMainPath() throws RepositoryException {
            return this.configNode.getPath();
        }

        boolean needsUpgrade() {
            return this.actionNode != null;
        }
    }

}