001/*
002 *  Copyright 2014 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.cms.workflow.archive;
017
018import java.util.Calendar;
019import java.util.Date;
020import java.util.GregorianCalendar;
021import java.util.Timer;
022import java.util.TimerTask;
023
024import org.apache.avalon.framework.activity.Disposable;
025import org.apache.avalon.framework.activity.Initializable;
026import org.apache.avalon.framework.configuration.Configurable;
027import org.apache.avalon.framework.configuration.Configuration;
028import org.apache.avalon.framework.configuration.ConfigurationException;
029import org.apache.avalon.framework.context.Context;
030import org.apache.avalon.framework.context.ContextException;
031import org.apache.avalon.framework.context.Contextualizable;
032import org.apache.avalon.framework.logger.LogEnabled;
033import org.apache.avalon.framework.logger.Logger;
034import org.apache.avalon.framework.service.ServiceException;
035import org.apache.avalon.framework.service.ServiceManager;
036import org.apache.avalon.framework.service.Serviceable;
037import org.apache.commons.lang.StringUtils;
038
039import org.ametys.runtime.config.Config;
040
041/**
042 * Archive contents scheduler: launches a cron which archives contents when
043 * necessary.
044 */
045public class ArchiveContentsScheduler extends TimerTask implements Initializable, LogEnabled, Serviceable, Disposable, Contextualizable, Configurable
046{
047    /** The service manager. */
048    protected ServiceManager _manager;
049
050    /** The component configuration. */
051    protected Configuration _configuration;
052
053    /** The avalon context. */
054    protected Context _context;
055
056    /** The logger. */
057    protected Logger _logger;
058
059    /** The timer. */
060    protected Timer _timer;
061
062    @Override
063    public void service(ServiceManager manager) throws ServiceException
064    {
065        _manager = manager;
066    }
067
068    @Override
069    public void contextualize(Context context) throws ContextException
070    {
071        _context = context;
072    }
073
074    @Override
075    public void configure(Configuration configuration) throws ConfigurationException
076    {
077        _configuration = configuration;
078    }
079
080    @Override
081    public void enableLogging(Logger logger)
082    {
083        _logger = logger;
084    }
085
086    @Override
087    public void initialize() throws Exception
088    {
089        boolean enabled = Config.getInstance().getValue("archive.scheduler.enabled");
090        if (!enabled)
091        {
092            return;
093        }
094        
095        if (_logger.isDebugEnabled())
096        {
097            _logger.debug("Initializing the archive scheduler...");
098        }
099
100        String hourStr = Config.getInstance().getValue("archive.scheduler.hour");
101
102        // Schedule a timer to run at the given hour, each defined period.
103        int hour = 0;
104        int minute = 0;
105        if (StringUtils.isNotEmpty(hourStr) && hourStr.indexOf(':') > 0)
106        {
107            String[] hourArray = StringUtils.split(hourStr, ':');
108            hour = Integer.parseInt(hourArray[0]);
109            minute = Integer.parseInt(hourArray[1]);
110        }
111
112        GregorianCalendar calendar = new GregorianCalendar();
113        calendar.set(Calendar.AM_PM, hour < 12 ? Calendar.AM : Calendar.PM);
114        calendar.set(Calendar.HOUR, hour % 12);
115        calendar.set(Calendar.MINUTE, minute);
116        calendar.set(Calendar.SECOND, 0);
117        calendar.set(Calendar.MILLISECOND, 0);
118
119        // Each day.
120        long period = 24 * 3600 * 1000;
121        Date firstTime = calendar.getTime();
122
123        Date now = new Date();
124
125        // If the given time today is past, schedule for tomorrow.
126        if (firstTime.compareTo(now) < 0)
127        {
128            calendar.add(Calendar.DAY_OF_MONTH, 1);
129            firstTime = calendar.getTime();
130        }
131
132        if (_logger.isInfoEnabled())
133        {
134            _logger.info("Archive contents scheduler: the archive engine will run every day at the hour, starting " + firstTime.toString());
135        }
136
137        _timer = new Timer("ArchiveContents", true);
138        _timer.schedule(this, firstTime, period);
139    }
140
141    @Override
142    public void run()
143    {
144        ArchiveContentsEngine archiveContentsEngine = new ArchiveContentsEngine();
145
146        try
147        {
148            // Initialize and configure the engine.
149            archiveContentsEngine.initialize(_manager, _context);
150            archiveContentsEngine.configure(_configuration);
151        }
152        catch (Exception e)
153        {
154            throw new RuntimeException("Unable to initialize the archive engine", e);
155        }
156
157        // The thread will be started as daemon, as the scheduler is marked
158        // daemon itself.
159        new Thread(archiveContentsEngine, "ArchiveContentsEngine").start();
160    }
161
162    @Override
163    public void dispose()
164    {
165        _context = null;
166        _logger = null;
167        _manager = null;
168        _configuration = null;
169
170        cancel();
171        if (_timer != null)
172        {
173            _timer.cancel();
174            _timer = null;
175        }
176    }
177
178}