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        if (!Config.getInstance().getValueAsBoolean("archive.scheduler.enabled"))
090        {
091            return;
092        }
093        
094        if (_logger.isDebugEnabled())
095        {
096            _logger.debug("Initializing the archive scheduler...");
097        }
098
099        String hourStr = Config.getInstance().getValueAsString("archive.scheduler.hour");
100
101        // Schedule a timer to run at the given hour, each defined period.
102        int hour = 0;
103        int minute = 0;
104        if (StringUtils.isNotEmpty(hourStr) && hourStr.indexOf(':') > 0)
105        {
106            String[] hourArray = StringUtils.split(hourStr, ':');
107            hour = Integer.parseInt(hourArray[0]);
108            minute = Integer.parseInt(hourArray[1]);
109        }
110
111        GregorianCalendar calendar = new GregorianCalendar();
112        calendar.set(Calendar.AM_PM, hour < 12 ? Calendar.AM : Calendar.PM);
113        calendar.set(Calendar.HOUR, hour % 12);
114        calendar.set(Calendar.MINUTE, minute);
115        calendar.set(Calendar.SECOND, 0);
116        calendar.set(Calendar.MILLISECOND, 0);
117
118        // Each day.
119        long period = 24 * 3600 * 1000;
120        Date firstTime = calendar.getTime();
121
122        Date now = new Date();
123
124        // If the given time today is past, schedule for tomorrow.
125        if (firstTime.compareTo(now) < 0)
126        {
127            calendar.add(Calendar.DAY_OF_MONTH, 1);
128            firstTime = calendar.getTime();
129        }
130
131        if (_logger.isInfoEnabled())
132        {
133            _logger.info("Archive contents scheduler: the archive engine will run every day at the hour, starting " + firstTime.toString());
134        }
135
136        _timer = new Timer("ArchiveContents", true);
137        _timer.schedule(this, firstTime, period);
138    }
139
140    @Override
141    public void run()
142    {
143        ArchiveContentsEngine archiveContentsEngine = new ArchiveContentsEngine();
144
145        try
146        {
147            // Initialize and configure the engine.
148            archiveContentsEngine.initialize(_manager, _context);
149            archiveContentsEngine.configure(_configuration);
150        }
151        catch (Exception e)
152        {
153            throw new RuntimeException("Unable to initialize the archive engine", e);
154        }
155
156        // The thread will be started as daemon, as the scheduler is marked
157        // daemon itself.
158        new Thread(archiveContentsEngine, "ArchiveContentsEngine").start();
159    }
160
161    @Override
162    public void dispose()
163    {
164        _context = null;
165        _logger = null;
166        _manager = null;
167        _configuration = null;
168
169        cancel();
170        if (_timer != null)
171        {
172            _timer.cancel();
173            _timer = null;
174        }
175    }
176
177}