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