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