BackupMerger.java 8.47 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.sling.jcr.resource.JcrResourceUtil
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.upgrades.backup.impl;

import com.adobe.cq.upgrades.backup.BackupConfig;
import com.adobe.cq.upgrades.backup.UpgradeBackupMerger;
import com.adobe.cq.upgrades.backup.impl.U;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.jcr.resource.JcrResourceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BackupMerger {
    private static final String MIXIN_REP_ACCESS_CONTROLLABLE = "rep:AccessControllable";
    private static final String PATH_REP_POLICY = "/rep:policy";
    private final Logger log;
    private final String backupRootPath;
    private final UpgradeBackupMerger.ProgressInfo progressInfo;
    private final BackupConfig backupConfig;

    public BackupMerger(String backupRootPath, BackupConfig backupConfig, UpgradeBackupMerger.ProgressInfo progressInfo) {
        this.log = LoggerFactory.getLogger(this.getClass());
        this.backupRootPath = backupRootPath;
        this.backupConfig = backupConfig;
        this.progressInfo = progressInfo;
    }

    private void safeMove(Session s, String src, String dest) {
        try {
            Node parent;
            String parentPath;
            if (dest.endsWith("/rep:policy") && (parent = s.getNode(parentPath = dest.substring(0, dest.length() - "/rep:policy".length()))).canAddMixin("rep:AccessControllable")) {
                parent.addMixin("rep:AccessControllable");
            }
            s.move(src, dest);
        }
        catch (Exception e) {
            this.log.warn("Failed to move {} to {}, source node won't be merged", new Object[]{src, dest, e});
        }
    }

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

    public void execute(Session sess) throws Exception {
        if (!sess.nodeExists(this.backupRootPath)) {
            this.setProgressInfo(this.backupRootPath + " does not exist, no content to merge");
            return;
        }
        ArrayList<Node> matchingNodes = new ArrayList<Node>();
        Node mainRoot = sess.getNode(this.backupRootPath);
        NodeIterator it = mainRoot.getNodes();
        while (it.hasNext()) {
            Node child = it.nextNode();
            if (!child.hasNode("to-process")) continue;
            matchingNodes.add(child.getNode("to-process"));
        }
        if (matchingNodes.size() == 0) {
            this.log.info("No backup node matching {} found under {}, no content to upgrade", (Object)"to-process", (Object)mainRoot.getPath());
            return;
        }
        if (matchingNodes.size() > 1) {
            Collections.sort(matchingNodes, new Comparator<Node>(){

                @Override
                public int compare(Node x, Node y) {
                    return y.toString().compareTo(x.toString());
                }
            });
        }
        Node backupRoot = (Node)matchingNodes.get(0);
        String overwrittenRootPath = backupRoot.getParent().getPath() + "/" + "overwritten";
        String leftoversRootPath = backupRoot.getParent().getPath() + "/" + "leftovers";
        NodeIterator it2 = backupRoot.getNodes();
        while (it2.hasNext()) {
            Node n = it2.nextNode();
            String restoreRootPath = n.getPath().substring(backupRoot.getPath().length());
            this.restore(n, restoreRootPath, overwrittenRootPath, leftoversRootPath);
        }
    }

    private void restore(Node backupRoot, String restoreRootPath, String overwrittenPath, String leftoversPath) throws RepositoryException {
        Session sess = backupRoot.getSession();
        Node restoreRoot = sess.getNode(restoreRootPath);
        this.setProgressInfo("Moving " + backupRoot.getPath() + " back under " + restoreRoot.getPath());
        AtomicInteger overwrittenCount = new AtomicInteger();
        JcrResourceUtil.createPath((String)overwrittenPath, (String)"nt:unstructured", (String)"nt:unstructured", (Session)sess, (boolean)false);
        this.moveOverwritesBack(backupRoot, backupRoot, restoreRoot, overwrittenPath, overwrittenCount);
        this.log.info("{} nodes restored in overwrite mode", (Object)overwrittenCount.get());
        AtomicInteger counter = new AtomicInteger();
        this.moveChildrenBack(backupRoot, backupRoot, restoreRoot, counter);
        sess.save();
        this.setProgressInfo(counter + " backup nodes processed");
        String dest = leftoversPath + restoreRoot.getPath();
        JcrResourceUtil.createPath((String)U.getParentPath(dest, 1), (String)"nt:unstructured", (String)"nt:unstructured", (Session)sess, (boolean)false);
        this.safeMove(sess, backupRoot.getPath(), dest);
        this.setProgressInfo("Remaining backup nodes moved under " + dest);
        sess.save();
    }

    private void moveOverwritesBack(Node src, Node backupRoot, Node destRoot, String overwrittenPath, AtomicInteger counter) throws RepositoryException {
        Set<String> pathsToOverwrite = this.backupConfig.getPathsToOverwrite();
        String destPath = this.getDestPath(src, backupRoot, destRoot);
        if (destPath != null && pathsToOverwrite.contains(destPath)) {
            String saveOverwrittenPath = overwrittenPath + destPath;
            Session s = src.getSession();
            if (s.nodeExists(destPath)) {
                this.log.info("Moving {} under {} - will be overwritten by backed up content", (Object)destPath, (Object)saveOverwrittenPath);
                String destFolder = U.getParentPath(saveOverwrittenPath, 1);
                JcrResourceUtil.createPath((String)destFolder, (String)"nt:unstructured", (String)"nt:unstructured", (Session)s, (boolean)false);
                this.safeMove(s, destPath, saveOverwrittenPath);
                s.save();
            }
            this.log.info("Moving {} under {} - overwrites old content", (Object)src.getPath(), (Object)destPath);
            String destParentPath = U.getParentPath(destPath, 1);
            if (!s.nodeExists(destParentPath)) {
                this.log.info("Destination parent {} does not exist, creating it as nt:unstructured", (Object)destParentPath);
                JcrResourceUtil.createPath((String)destParentPath, (String)"nt:unstructured", (String)"nt:unstructured", (Session)s, (boolean)false);
            }
            this.safeMove(s, src.getPath(), destPath);
            s.save();
            counter.incrementAndGet();
        } else {
            NodeIterator it = src.getNodes();
            while (it.hasNext()) {
                this.moveOverwritesBack(it.nextNode(), backupRoot, destRoot, overwrittenPath, counter);
            }
        }
    }

    private void moveChildrenBack(Node src, Node backupRoot, Node destRoot, AtomicInteger counter) throws RepositoryException {
        NodeIterator it = src.getNodes();
        while (it.hasNext()) {
            Node child = it.nextNode();
            String destPath = this.getDestPath(child, backupRoot, destRoot);
            counter.incrementAndGet();
            if (child.getSession().nodeExists(destPath)) {
                this.log.info("Destination {} exists, backup node ignored: {}", (Object)destPath, (Object)child.getPath());
                this.moveChildrenBack(child, backupRoot, destRoot, counter);
            } else {
                this.log.info("Moving {} back to {}", (Object)child.getPath(), (Object)destPath);
                this.safeMove(child.getSession(), child.getPath(), destPath);
            }
            if (counter.get() % 10 != 0) continue;
            src.getSession().save();
            this.setProgressInfo(counter + " backup nodes processed");
        }
    }

    private String getDestPath(Node src, Node backupRoot, Node destRoot) throws RepositoryException {
        try {
            return destRoot.getPath() + src.getPath().substring(backupRoot.getPath().length());
        }
        catch (StringIndexOutOfBoundsException oob) {
            this.log.warn("Cannot compute destination path for {} with backup root {} and destination root {}", new Object[]{src.getPath(), backupRoot.getPath(), destRoot.getPath()});
            return null;
        }
    }

}