UpgradeBackup.java 7.92 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.Node
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.felix.scr.annotations.Activate
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Deactivate
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.sling.jcr.api.SlingRepository
 *  org.apache.sling.launchpad.api.StartupHandler
 *  org.apache.sling.launchpad.api.StartupMode
 *  org.osgi.framework.BundleContext
 *  org.osgi.framework.FrameworkEvent
 *  org.osgi.framework.FrameworkListener
 *  org.osgi.service.component.ComponentContext
 *  org.osgi.service.startlevel.StartLevel
 *  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.impl.U;
import com.day.cq.commons.jcr.JcrUtil;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.launchpad.api.StartupHandler;
import org.apache.sling.launchpad.api.StartupMode;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.startlevel.StartLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
public class UpgradeBackup
implements FrameworkListener {
    private final Logger log;
    private final String uniqueId;
    @Reference
    private SlingRepository repository;
    @Reference
    private StartupHandler startupHandler;
    @Reference
    private StartLevel startLevel;
    @Reference
    private BackupConfig backupConfig;
    private State state;

    public UpgradeBackup() {
        this.log = LoggerFactory.getLogger(this.getClass());
        this.uniqueId = new SimpleDateFormat("yyyyMMdd_HHmmss_S").format(new Date());
        this.state = State.INACTIVE;
    }

    public void frameworkEvent(FrameworkEvent e) {
        if (e.getType() == 8) {
            if (this.state == State.INACTIVE) {
                this.log.warn("Unexpected: getting STARTLEVEL_CHANGED events while inactive");
            } else if (this.state != State.LOGGED) {
                if (this.state == State.DONE) {
                    this.log.info("STARTLEVEL_CHANGED to {}, status is DONE, all good", (Object)this.startLevel.getStartLevel());
                    this.state = State.LOGGED;
                } else {
                    this.log.warn("STARTLEVEL_CHANGED to {} and backup is not done, state={}", (Object)this.startLevel.getStartLevel(), (Object)this.state.toString());
                }
            }
        }
    }

    @Activate
    protected void activate(ComponentContext ctx) {
        this.state = State.INIT;
        BundleContext bc = ctx.getBundleContext();
        bc.addFrameworkListener((FrameworkListener)this);
        try {
            StartupMode sm = this.startupHandler.getMode();
            if (sm == StartupMode.UPDATE) {
                this.log.info("Startup mode is {}, backup will be done", (Object)sm);
            } else if (this.backupForced()) {
                this.log.info("Startup mode is {} but backup is forced, backup will be done", (Object)sm);
            } else {
                this.log.info("Startup mode is {}, nothing to do", (Object)sm);
                this.state = State.DONE;
                return;
            }
            this.state = State.BACKUP;
            this.backup();
            this.log.info("Backup done");
            this.state = State.DONE;
        }
        catch (Exception e) {
            this.log.warn("Exception in activate()", (Throwable)e);
            this.state = State.ERROR;
        }
    }

    @Deactivate
    protected void deactivate(ComponentContext ctx) {
        this.state = State.INACTIVE;
        ctx.getBundleContext().removeFrameworkListener((FrameworkListener)this);
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private boolean backupForced() throws RepositoryException {
        boolean result;
        block5 : {
            result = false;
            Session s = null;
            try {
                s = this.repository.loginAdministrative(null);
                if (s.itemExists("/var/upgrade/status/preUpgradeBackup.force")) {
                    this.log.info("property {} exists, forcing backup", (Object)"/var/upgrade/status/preUpgradeBackup.force");
                    result = true;
                    break block5;
                }
                this.log.info("property {} does not exist, backup will not be forced", (Object)"/var/upgrade/status/preUpgradeBackup.force");
            }
            finally {
                if (s != null) {
                    s.logout();
                }
            }
        }
        return result;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private void backup() throws RepositoryException {
        Session s = this.repository.loginAdministrative(null);
        this.backupConfig.readConfig(s);
        try {
            Node backupRoot = this.getBackupFolder(s, "to-process");
            this.log.info("Backing up content before upgrade, destination={}", (Object)backupRoot.getPath());
            for (String path : this.backupConfig.getPathsToBackup()) {
                if (!s.nodeExists(path)) {
                    this.log.warn("Source path not found, nothing to backup: {}", (Object)path);
                    continue;
                }
                String dest = backupRoot.getPath() + path;
                JcrUtil.createPath(U.getParentPath(dest, 1), "nt:unstructured", s);
                this.log.info("Moving {} to {}", (Object)path, (Object)dest);
                s.move(path, dest);
            }
            s.save();
        }
        finally {
            if (s != null) {
                s.logout();
            }
        }
    }

    private Node getBackupFolder(Session s, String folderName) throws RepositoryException {
        JcrUtil.createPath("/var/upgrade/PreUpgradeBackup", "nt:unstructured", s);
        Node result = JcrUtil.createPath("/var/upgrade/PreUpgradeBackup/" + this.uniqueId + "/" + folderName, "sling:Folder", s);
        if (s.hasPendingChanges()) {
            s.save();
        }
        return result;
    }

    protected void bindRepository(SlingRepository slingRepository) {
        this.repository = slingRepository;
    }

    protected void unbindRepository(SlingRepository slingRepository) {
        if (this.repository == slingRepository) {
            this.repository = null;
        }
    }

    protected void bindStartupHandler(StartupHandler startupHandler) {
        this.startupHandler = startupHandler;
    }

    protected void unbindStartupHandler(StartupHandler startupHandler) {
        if (this.startupHandler == startupHandler) {
            this.startupHandler = null;
        }
    }

    protected void bindStartLevel(StartLevel startLevel) {
        this.startLevel = startLevel;
    }

    protected void unbindStartLevel(StartLevel startLevel) {
        if (this.startLevel == startLevel) {
            this.startLevel = null;
        }
    }

    protected void bindBackupConfig(BackupConfig backupConfig) {
        this.backupConfig = backupConfig;
    }

    protected void unbindBackupConfig(BackupConfig backupConfig) {
        if (this.backupConfig == backupConfig) {
            this.backupConfig = null;
        }
    }

    private static enum State {
        INACTIVE,
        INIT,
        BACKUP,
        DONE,
        LOGGED,
        ERROR;
        

        private State() {
        }
    }

}