001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Florent Guillaume
016 */
017package org.nuxeo.ecm.core.storage.sql;
018
019import java.util.Calendar;
020
021import org.apache.commons.logging.Log;
022import org.apache.commons.logging.LogFactory;
023import org.nuxeo.ecm.core.event.Event;
024import org.nuxeo.ecm.core.event.EventListener;
025import org.nuxeo.ecm.core.storage.sql.coremodel.SQLRepositoryService;
026import org.nuxeo.runtime.api.Framework;
027
028/**
029 * Sync listener that calls the soft delete cleanup method of the repositories. Designed to be called periodically.
030 *
031 * @since 5.7
032 */
033public class SoftDeleteCleanupListener implements EventListener {
034
035    private static final Log log = LogFactory.getLog(SoftDeleteCleanupListener.class);
036
037    public static final int DEFAULT_MAX = 1000;
038
039    /**
040     * Property for the maximum number of documents to delete in one call. Zero means all the documents. Default is
041     * {@value #DEFAULT_MAX}.
042     */
043    public static final String DEFAULT_MAX_PROP = "org.nuxeo.vcs.softdelete.cleanup.max";
044
045    public static final int DEFAULT_DELAY = 5 * 60; // 5 min
046
047    /**
048     * Property for the minimum delay (in seconds) since when a document must have been soft-deleted before it can be
049     * hard-deleted. Zero means no delay. Default is {@value #DEFAULT_DELAY}.
050     */
051    public static final String DEFAULT_DELAY_PROP = "org.nuxeo.vcs.softdelete.cleanup.age";
052
053    /**
054     * Gets the maximum number of documents to delete in one call. Zero means all the documents.
055     */
056    protected int getMax() {
057        String max = Framework.getProperty(DEFAULT_MAX_PROP);
058        if (max == null) {
059            return DEFAULT_MAX;
060        }
061        try {
062            return Integer.parseInt(max);
063        } catch (NumberFormatException e) {
064            log.error("Invalid property " + DEFAULT_MAX_PROP, e);
065            return DEFAULT_MAX;
066        }
067    }
068
069    /**
070     * Gets the minimum delay (in seconds) since when a document must have been soft-deleted before it can be
071     * hard-deleted. Zero means no delay.
072     */
073    protected int getDelaySeconds() {
074        String delay = Framework.getProperty(DEFAULT_DELAY_PROP);
075        if (delay == null) {
076            return DEFAULT_DELAY;
077        }
078        try {
079            return Integer.parseInt(delay);
080        } catch (NumberFormatException e) {
081            log.error("Invalid property " + DEFAULT_DELAY_PROP, e);
082            return DEFAULT_DELAY;
083        }
084    }
085
086    @Override
087    public void handleEvent(Event event) {
088        int max = getMax();
089        int delay = getDelaySeconds();
090        Calendar beforeTime;
091        if (delay <= 0) {
092            beforeTime = null;
093        } else {
094            beforeTime = Calendar.getInstance();
095            beforeTime.add(Calendar.SECOND, -delay);
096        }
097        SQLRepositoryService sqlRepositoryService = Framework.getService(SQLRepositoryService.class);
098        for (RepositoryManagement repoMgmt : sqlRepositoryService.getRepositories()) {
099            log.debug("Calling repository soft-delete cleanup for repository: " + repoMgmt.getName() + ", max=" + max
100                    + ", beforeTimeDelay=" + delay);
101            int n = repoMgmt.cleanupDeletedDocuments(max, beforeTime);
102            log.debug("Number of documents deleted: " + n);
103        }
104    }
105
106}