001/*
002 *  Copyright 2011 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.purge;
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 * Purge contents scheduler: launches a cron which purges contents at a given periodicity.
043 */
044public class PurgeContentsScheduler extends TimerTask implements Initializable, LogEnabled, Serviceable, Disposable, Contextualizable, Configurable
045{
046    
047    /** The default period, in days. */
048    private static final long _DEFAULT_PERIOD = 7;
049    
050    /** The service manager. */
051    protected ServiceManager _manager;
052    
053    /** The component configuration. */
054    protected Configuration _configuration;
055    
056    /** The avalon context. */
057    protected Context _context;
058    
059    /** The logger. */
060    protected Logger _logger;
061    
062    /** The timer. */
063    protected Timer _timer;
064    
065    @Override
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        _manager = manager;
069    }
070    
071    @Override
072    public void contextualize(Context context) throws ContextException
073    {
074        _context = context;
075    }
076    
077    @Override
078    public void configure(Configuration configuration) throws ConfigurationException
079    {
080        _configuration = configuration;
081    }
082    
083    @Override
084    public void enableLogging(Logger logger)
085    {
086        _logger = logger;
087    }
088    
089    @Override
090    public void initialize() throws Exception
091    {
092        if (_logger.isDebugEnabled())
093        {
094            _logger.debug("Initializing the alert scheduler...");
095        }
096        
097        Boolean enabled = Config.getInstance().getValueAsBoolean("purge.scheduler.enabled");
098        
099        if (enabled != null && enabled)
100        {
101            Long periodDays = Config.getInstance().getValueAsLong("purge.scheduler.period");
102            if (periodDays == null)
103            {
104                periodDays = _DEFAULT_PERIOD;
105            }
106            String hourStr = Config.getInstance().getValueAsString("purge.scheduler.hour");
107            
108            // Schedule a timer to run at the given hour, each defined period.
109            int hour = 0;
110            int minute = 0;
111            if (StringUtils.isNotEmpty(hourStr) && hourStr.indexOf(':') > 0)
112            {
113                String[] hourArray = StringUtils.split(hourStr, ':');
114                hour = Integer.parseInt(hourArray[0]);
115                minute = Integer.parseInt(hourArray[1]);
116            }
117            
118            GregorianCalendar calendar = new GregorianCalendar();
119            calendar.set(Calendar.AM_PM, hour < 12 ? Calendar.AM : Calendar.PM);
120            calendar.set(Calendar.HOUR, hour % 12);
121            calendar.set(Calendar.MINUTE, minute);
122            calendar.set(Calendar.SECOND, 0);
123            calendar.set(Calendar.MILLISECOND, 0);
124            
125//            calendar.add(Calendar.MINUTE, 1);
126            
127            // Each day.
128            long period = periodDays * 24 * 3600 * 1000;
129            Date firstTime = calendar.getTime();
130    
131            Date now = new Date();
132    
133            // If the given time today is past, schedule for tomorrow.
134            if (firstTime.compareTo(now) < 0)
135            {
136                calendar.add(Calendar.DAY_OF_MONTH, 1);
137                firstTime = calendar.getTime();
138            }
139            
140            if (_logger.isInfoEnabled())
141            {
142                _logger.info("Purge contents scheduler: the purge engine will run every " + periodDays + " days, starting " + firstTime.toString());
143            }
144            
145            _timer = new Timer("PurgeContents", true);
146            _timer.schedule(this, firstTime, period);
147        }
148    }
149    
150    @Override
151    public void run()
152    {
153        PurgeContentsEngine purgeContentsEngine = new PurgeContentsEngine();
154        
155        try
156        {
157            // Initialize and configure the engine.
158            purgeContentsEngine.initialize(_manager, _context);
159            purgeContentsEngine.configure(_configuration);
160        }
161        catch (Exception e)
162        {
163            throw new RuntimeException("Unable to initialize the alerts engine", e);
164        }
165        
166        // The thread will be started as daemon, as the scheduler is marked daemon itself.
167        new Thread(purgeContentsEngine, "PurgeContentsEngine").start();
168    }
169    
170    @Override
171    public void dispose()
172    {
173        _context = null;
174        _logger = null;
175        _manager = null;
176        _configuration = null;
177        
178        cancel();
179        if (_timer != null)
180        {
181            _timer.cancel();
182            _timer = null;
183        }
184    }
185    
186}