001/*
002*  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013*  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.workspaces.repository.maintenance;
017
018import java.util.Map;
019
020import javax.jcr.RepositoryException;
021
022import org.apache.commons.lang.StringUtils;
023import org.apache.jackrabbit.core.config.RepositoryConfig;
024import org.slf4j.Logger;
025
026import org.ametys.core.util.DateUtils;
027import org.ametys.plugins.repositoryapp.RepositoryProvider;
028import org.ametys.runtime.plugin.component.LogEnabled;
029
030/**
031 * Jackrabbit maintenance tasks implementations should extends this class.
032 */
033public abstract class AbstractMaintenanceTask implements LogEnabled
034{
035    /** TaskProgress */
036    protected TaskProgress _progress;
037
038    /** The repository config */
039    protected RepositoryConfig _repositoryConfig;
040
041    /** The repository provider. */
042    protected RepositoryProvider _repositoryProvider;
043    
044    /** Logger for traces */
045    protected Logger _logger;
046    
047    private boolean _isFinished;
048    
049    /**
050     * Execute the task
051     * @param repositoryConfig The RepositoryConfig object, used to create new Repository instance.
052     * @throws RepositoryException If an error with the repository occurs while the task is executed.
053     */
054    public void execute(RepositoryConfig repositoryConfig) throws RepositoryException 
055    {
056        _repositoryConfig = repositoryConfig;
057
058        long startTime = System.currentTimeMillis();
059        
060        setLogger();
061
062        _logger.info("Executing task.");
063
064        try
065        {
066            // task specific initialization.
067            initialize();
068
069            // Mark the task as running.
070            setRunning();
071
072            // Perform the task.
073            apply();
074
075            // Mark the task as finished.
076            setFinished();
077        }
078        catch (Exception e)
079        {
080            setInErrorState(e);
081            throw e;
082        }
083        finally
084        {
085            close();
086
087            _logger.info("End of the task.");
088
089            long elapsedTime = System.currentTimeMillis() - startTime;
090            _logger.info("Done in " + _getFormattedDuration(elapsedTime));
091        }
092    }
093
094    /**
095     * Initialize the tasks.
096     * This method can also create the {@link TaskProgress} object bounded to the task.
097     * @throws RepositoryException If a repository exception
098     */
099    protected void initialize() throws RepositoryException
100    {
101        return;
102    }
103    
104    /**
105     * Set the tasks logger.
106     */
107    protected abstract void setLogger();
108    
109    @Override
110    public void setLogger(Logger logger)
111    {
112        _logger = logger;
113    }
114
115    /**
116     * Apply the tasks (within the execute method()).
117     * @throws RepositoryException If a repository exception
118     */
119    protected abstract void apply() throws RepositoryException;
120
121    /**
122     * Close the tasks
123     * @throws RepositoryException If a repository exception
124     */
125    protected void close() throws RepositoryException
126    {
127        return;
128    }
129
130    /**
131     * Get progress information.
132     * @return a map containing information on the progress status.
133     */
134    public Map<String, Object> getProgressInfo() 
135    {
136        if (_progress != null)
137        {
138            return _progress.getProgressInfo();
139        }
140        else
141        {
142            return null;
143        }
144    }
145
146    /**
147     * Is the execution of the task finished?
148     * @return true if finished
149     */
150    public boolean isFinished()
151    {
152        return _isFinished;
153    }
154
155    private synchronized void setRunning()
156    {
157        if (_progress != null)
158        {
159            _progress.setRunning();
160        }
161    }
162
163    private synchronized void setFinished()
164    {
165        if (_progress != null)
166        {
167            _progress.setFinished();
168        }
169
170        _isFinished = true;
171    }
172
173    private synchronized void setInErrorState(Exception e)
174    {
175        _logger.error(e.getLocalizedMessage(), e);
176
177        if (_progress != null)
178        {
179            _progress.setInErrorState(e);
180        }
181
182        _isFinished = true;
183    }
184
185    /**
186     * Transforms millisecond to a formatted string representing a duration.
187     * @param elapsedTime milleseconds corresponding to the duration.
188     * @return Pretty formatted string.
189     */
190    protected String _getFormattedDuration(long elapsedTime)
191    {
192        String formatted = DateUtils.formatDuration(elapsedTime);
193        return StringUtils.defaultIfEmpty(formatted, "0s");
194    }
195}