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.plugins.core.impl.schedule;
017
018import java.util.LinkedHashMap;
019import java.util.Map;
020
021import org.apache.avalon.framework.component.Component;
022import org.apache.avalon.framework.configuration.Configurable;
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031import org.quartz.JobExecutionContext;
032
033import org.ametys.core.schedule.Schedulable;
034import org.ametys.core.schedule.SchedulableParameterTypeExtensionPoint;
035import org.ametys.core.user.UserManager;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.runtime.model.ElementDefinition;
038import org.ametys.runtime.model.ElementDefinitionParser;
039import org.ametys.runtime.model.Enumerator;
040import org.ametys.runtime.parameter.Validator;
041import org.ametys.runtime.plugin.component.AbstractLogEnabled;
042import org.ametys.runtime.plugin.component.PluginAware;
043import org.ametys.runtime.plugin.component.ThreadSafeComponentManager;
044
045/**
046 * Default static implementation of {@link Schedulable}
047 * For implementing the {@link Schedulable} interface (while being {@link Configurable}), extends this class and implements the {@link #execute(org.quartz.JobExecutionContext)} method
048 * <br>
049 * For instance:
050 * <pre>
051 * public class SayHelloSchedulable extends AbstractStaticSchedulable
052 * {
053 *     public static final String FIRSTNAME_KEY = "firstName";
054 *     
055 *     private static final String __JOBDATAMAP_FIRSTNAME_KEY = Scheduler.PARAM_VALUES_PREFIX + FIRSTNAME_KEY;
056 *     
057 *     public void execute(JobExecutionContext context) throws Exception
058 *     {
059 *         JobKey jobKey = context.getJobDetail().getKey();
060 *         JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
061 *         String name = jobDataMap.getString(__JOBDATAMAP_FIRSTNAME_KEY);
062 *         System.out.println("[" + jobKey + "] " + new Date() + " - Hello  " + name + "!");
063 *     }
064 * }
065 * </pre>
066 */
067public abstract class AbstractStaticSchedulable extends AbstractLogEnabled implements Schedulable, Component, Configurable, PluginAware, Serviceable, Contextualizable
068{
069    /** The name of the plugin that has declared this component */
070    protected String _pluginName;
071    /** The id of this extension */
072    protected String _id;
073    /** The service manager */
074    protected ServiceManager _smanager;
075    /** The context */
076    protected Context _context;
077    /** The label */
078    protected I18nizableText _label;
079    /** The description */
080    protected I18nizableText _description;
081    /** The icon glyph */
082    protected String _iconGlyph;
083    /** The small icon */
084    protected String _iconSmall;
085    /** The medium icon */
086    protected String _iconMedium;
087    /** The large icon */
088    protected String _iconLarge;
089    /** True if the schedulable is private */
090    protected boolean _private;
091    /** True if two runnables of this schedulable can be executed concurrently */
092    protected boolean _acceptConcurrentExecution;
093    /** The parameters */
094    protected Map<String, ElementDefinition> _parameters;
095    /** The Schedulable Extension Point */
096    protected SchedulableParameterTypeExtensionPoint _schedulableParameterTypeExtensionPoint;
097    /** The user manager */
098    protected UserManager _userManager;
099    
100    @Override
101    public void setPluginInfo(String pluginName, String featureName, String id)
102    {
103        _pluginName = pluginName;
104        _id = id;
105    }
106    
107    @Override
108    public void contextualize(Context context) throws ContextException
109    {
110        _context = context;
111    }
112    
113    @Override
114    public void service(ServiceManager manager) throws ServiceException
115    {
116        _smanager = manager;
117        _schedulableParameterTypeExtensionPoint = (SchedulableParameterTypeExtensionPoint) _smanager.lookup(SchedulableParameterTypeExtensionPoint.ROLE);
118        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
119    }
120    
121    @Override
122    public void configure(Configuration configuration) throws ConfigurationException
123    {
124        _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin." + _pluginName);
125        _description = I18nizableText.parseI18nizableText(configuration.getChild("description"), "plugin." + _pluginName);
126        _iconGlyph = configuration.getChild("icon-glyph").getValue("");
127        _iconSmall = configuration.getChild("icon-small").getValue("");
128        _iconMedium = configuration.getChild("icon-medium").getValue("");
129        _iconLarge = configuration.getChild("icon-large").getValue("");
130        _private = configuration.getChild("private").getValueAsBoolean(false);
131        _acceptConcurrentExecution = configuration.getChild("acceptConcurrentExecution").getValueAsBoolean(true);
132        _configureParameters(configuration.getChild("parameters"));
133    }
134    
135    private void _configureParameters(Configuration paramConfigs) throws ConfigurationException
136    {
137        _parameters = new LinkedHashMap<>();
138        
139        ThreadSafeComponentManager<Validator> validatorManager = new ThreadSafeComponentManager<>();
140        validatorManager.setLogger(getLogger());
141        validatorManager.contextualize(_context);
142        validatorManager.service(_smanager);
143        
144        ThreadSafeComponentManager<Enumerator> enumeratorManager = new ThreadSafeComponentManager<>();
145        enumeratorManager.setLogger(getLogger());
146        enumeratorManager.contextualize(_context);
147        enumeratorManager.service(_smanager);
148        
149        SchedulableParameterParser paramParser = new SchedulableParameterParser(_schedulableParameterTypeExtensionPoint, enumeratorManager, validatorManager);
150        for (Configuration paramConf : paramConfigs.getChildren("param"))
151        {
152            ElementDefinition definition = paramParser.parse(_smanager, _pluginName, paramConf, null, null);
153            String id = definition.getName();
154            
155            if (_parameters.containsKey(id))
156            {
157                throw new ConfigurationException("The parameter '" + id + "' is already declared. IDs must be unique.", paramConf);
158            }
159            
160            _parameters.put(id, definition);
161        }
162        
163        try
164        {
165            paramParser.lookupComponents();
166        }
167        catch (Exception e)
168        {
169            throw new ConfigurationException("Unable to lookup parameter local components", paramConfigs, e);
170        }
171    }
172    
173    @Override
174    public abstract void execute(JobExecutionContext context) throws Exception;
175    
176    @Override
177    public String getId()
178    {
179        return _id;
180    }
181
182    @Override
183    public I18nizableText getLabel()
184    {
185        return _label;
186    }
187
188    @Override
189    public I18nizableText getDescription()
190    {
191        return _description;
192    }
193
194    @Override
195    public String getIconGlyph()
196    {
197        return _iconGlyph;
198    }
199
200    @Override
201    public String getIconSmall()
202    {
203        return _iconSmall;
204    }
205
206    @Override
207    public String getIconMedium()
208    {
209        return _iconMedium;
210    }
211
212    @Override
213    public String getIconLarge()
214    {
215        return _iconLarge;
216    }
217    
218    @Override
219    public boolean isPrivate()
220    {
221        return _private;
222    }
223    
224    @Override
225    public boolean acceptConcurrentExecution()
226    {
227        return _acceptConcurrentExecution;
228    }
229
230    @Override
231    public Map<String, ElementDefinition> getParameters()
232    {
233        return _parameters;
234    }
235    
236    /**
237     * Class for parsing parameters of a {@link Schedulable}
238     */
239    public class SchedulableParameterParser extends ElementDefinitionParser
240    {
241        /**
242         * Constructor
243         * @param schedulableParameterTypeExtensionPoint the extension point to use to get available element types
244         * @param enumeratorManager The manager for enumeration
245         * @param validatorManager The manager for validation
246         */
247        public SchedulableParameterParser(SchedulableParameterTypeExtensionPoint schedulableParameterTypeExtensionPoint, ThreadSafeComponentManager<Enumerator> enumeratorManager, ThreadSafeComponentManager<Validator> validatorManager)
248        {
249            super(schedulableParameterTypeExtensionPoint, enumeratorManager, validatorManager);
250        }
251        
252        @Override
253        protected String _getNameConfigurationAttribute()
254        {
255            return "id";
256        }
257    }
258}