RecursiveDelete.java 6.27 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.RepositoryException
 *  javax.jcr.nodetype.NodeDefinition
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.crx.explorer.impl.util;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RecursiveDelete {
    private static final Logger log = LoggerFactory.getLogger(RecursiveDelete.class);
    private int batchSize = 1024;
    private Listener listener;
    private Node rootNode;
    private int numNodes = 0;
    private int numRemoved = 0;
    private long startTime;
    private boolean scan;
    private boolean dryRun;

    public RecursiveDelete(Node node) throws RepositoryException {
        this.rootNode = node;
        if (node.getDepth() == 0) {
            throw new IllegalArgumentException("Deletion of root node not supported.");
        }
    }

    public int getBatchSize() {
        return this.batchSize;
    }

    public void setBatchSize(int batchSize) {
        this.batchSize = batchSize;
    }

    public boolean isScanning() {
        return this.scan;
    }

    public void setScanning(boolean scan) {
        this.scan = scan;
    }

    public boolean isDryRun() {
        return this.dryRun;
    }

    public void setDryRun(boolean dryRun) {
        this.dryRun = dryRun;
    }

    public Listener getListener() {
        return this.listener;
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    public int run() throws RepositoryException {
        if (this.rootNode == null) {
            throw new IllegalStateException("Operation already peformed.");
        }
        Node parentNode = this.rootNode.getParent();
        if (parentNode.isNew() || parentNode.isModified()) {
            throw new IllegalArgumentException("Refuse to operate on a transiently modified node.");
        }
        String rootPath = this.rootNode.getPath();
        try {
            this.numNodes = 0;
            if (this.scan) {
                if (this.listener != null) {
                    this.listener.onStartScanning(rootPath);
                }
                this.count(this.rootNode);
                if (this.listener != null) {
                    this.listener.onEndScanning(rootPath, this.numNodes);
                }
            }
            if (this.listener != null) {
                this.listener.onStartDeleting(rootPath);
            }
            this.startTime = System.currentTimeMillis();
            int currentSize = this.delete(this.rootNode);
            this.save(parentNode, currentSize, true);
            long time = System.currentTimeMillis() - this.startTime;
            if (this.listener != null) {
                this.listener.onEndDeleting(rootPath, this.numNodes, time);
            }
        }
        catch (RepositoryException e) {
            try {
                parentNode.refresh(false);
            }
            catch (RepositoryException e1) {
                log.error("Refreshing the parent node failed: " + rootPath, (Throwable)e1);
            }
            log.error("Error during delete operation on " + rootPath, (Throwable)e);
            throw e;
        }
        this.rootNode = null;
        log.info("Recursively deleted {} nodes from {}", (Object)String.valueOf(this.numNodes), (Object)rootPath);
        return this.numNodes;
    }

    private void count(Node node) throws RepositoryException {
        NodeIterator iter = node.getNodes();
        while (iter.hasNext()) {
            this.count(iter.nextNode());
        }
        ++this.numNodes;
        if (this.listener != null) {
            this.listener.onScan(node.getPath(), this.numNodes);
        }
    }

    private int delete(Node node) throws RepositoryException {
        NodeDefinition def;
        int currentSize = this.deleteChildNodes(node);
        if (this.listener != null) {
            this.listener.onRemove(node.getPath(), this.numRemoved, this.numNodes);
        }
        if (!((def = node.getDefinition()).isMandatory() || def.isProtected() || this.dryRun)) {
            node.remove();
        }
        ++this.numRemoved;
        return currentSize + 1;
    }

    private int deleteChildNodes(Node node) throws RepositoryException {
        NodeIterator iter = node.getNodes();
        long size = iter.getSize();
        if (size > 0 && !this.scan) {
            this.numNodes = (int)((long)this.numNodes + size);
        }
        int currentSize = 0;
        while (iter.hasNext()) {
            Node child = iter.nextNode();
            if (size < 0 && !this.scan) {
                ++this.numNodes;
            }
            if (!this.save(node, currentSize += this.delete(child), false)) continue;
            currentSize = 0;
        }
        return currentSize;
    }

    private boolean save(Node node, int currentSize, boolean force) throws RepositoryException {
        if (currentSize >= this.batchSize || force) {
            long time = System.currentTimeMillis() - this.startTime;
            long eta = time * (long)(this.numNodes - this.numRemoved) / (long)this.numRemoved;
            StringBuffer msg = new StringBuffer("deleting ").append(currentSize).append(" nodes on ").append(node.getPath()).append(" (").append(this.numRemoved).append(" / ").append(this.numNodes).append(") ").append(eta).append("ms remaining.");
            log.info(msg.toString());
            if (this.listener != null) {
                this.listener.onBatchSave(node.getPath(), currentSize, this.numRemoved, this.numNodes, time, eta);
            }
            if (!this.dryRun) {
                node.save();
            }
            return true;
        }
        return false;
    }

    public static interface Listener {
        public void onStartDeleting(String var1);

        public void onEndDeleting(String var1, int var2, long var3);

        public void onStartScanning(String var1);

        public void onEndScanning(String var1, int var2);

        public void onRemove(String var1, int var2, int var3);

        public void onBatchSave(String var1, int var2, int var3, int var4, long var5, long var7);

        public void onScan(String var1, int var2);
    }

}