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.HashMap; 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.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.avalon.framework.service.Serviceable; 028 029import org.ametys.core.schedule.Runnable; 030import org.ametys.core.schedule.Runnable.MisfirePolicy; 031import org.ametys.core.schedule.RunnableExtensionPoint; 032import org.ametys.core.schedule.Schedulable; 033import org.ametys.core.schedule.SchedulableExtensionPoint; 034import org.ametys.core.user.UserIdentity; 035import org.ametys.core.user.population.UserPopulationDAO; 036import org.ametys.runtime.i18n.I18nizableText; 037import org.ametys.runtime.model.ElementDefinition; 038import org.ametys.runtime.model.type.ElementType; 039import org.ametys.runtime.plugin.component.PluginAware; 040 041/** 042 * Static implementation of {@link Runnable} which is configurable 043 */ 044public class StaticRunnable implements Runnable, Component, Configurable, PluginAware, Serviceable 045{ 046 /** The extension point for {@link Schedulable}s */ 047 protected SchedulableExtensionPoint _schedulableEP; 048 /** The name of the plugin that declared this component */ 049 protected String _pluginName; 050 /** The name of the feature that declared this component */ 051 protected String _featureName; 052 /** The id of this extension */ 053 protected String _id; 054 /** The label */ 055 protected I18nizableText _label; 056 /** The description */ 057 protected I18nizableText _description; 058 /** The fire process */ 059 protected FireProcess _fireProcess; 060 /** The CRON expression for scheduling the job */ 061 protected String _cronExpression; 062 /** The id of the {@link Schedulable} to execute */ 063 protected String _schedulableId; 064 /** Can the runnable be removed */ 065 protected boolean _removable; 066 /** Can the runnable be edited */ 067 protected boolean _modifiable; 068 /** Can the runnable be deactivated */ 069 protected boolean _deactivatable; 070 /** The misfire policy. Default to {@link MisfirePolicy#DO_NOTHING} */ 071 protected MisfirePolicy _misfirePolicy; 072 /** The parameter values */ 073 protected Map<String, Object> _parameterValues; 074 075 @Override 076 public void service(ServiceManager manager) throws ServiceException 077 { 078 _schedulableEP = (SchedulableExtensionPoint) manager.lookup(SchedulableExtensionPoint.ROLE); 079 } 080 081 @Override 082 public void setPluginInfo(String pluginName, String featureName, String id) 083 { 084 _pluginName = pluginName; 085 _featureName = featureName; 086 _id = id; 087 } 088 089 @Override 090 public void configure(Configuration configuration) throws ConfigurationException 091 { 092 _label = I18nizableText.parseI18nizableText(configuration.getChild("label"), "plugin." + _pluginName); 093 _description = I18nizableText.parseI18nizableText(configuration.getChild("description"), "plugin." + _pluginName); 094 _fireProcess = FireProcess.valueOf(configuration.getChild("fire-process").getValue("cron").toUpperCase()); 095 _cronExpression = configuration.getChild("cron").getValue("0 0 2 * * ? *"); 096 _schedulableId = configuration.getChild("schedulableId").getValue(); 097 if (!_schedulableEP.hasExtension(_schedulableId)) 098 { 099 String message = String.format("The extension '%s' of point '%s' declared in the feature '%s' in the plugin '%s' references the Schedulable extension '%s' but it seems to not exist.", 100 _id, RunnableExtensionPoint.class.getName(), _featureName, _pluginName, _schedulableId); 101 throw new ConfigurationException(message, configuration); 102 } 103 104 _removable = configuration.getChild("removable").getValueAsBoolean(false); 105 _modifiable = configuration.getChild("modifiable").getValueAsBoolean(false); 106 _deactivatable = configuration.getChild("deactivatable").getValueAsBoolean(false); 107 _misfirePolicy = MisfirePolicy.valueOf(configuration.getChild("misfire-policy").getValue("do_nothing").toUpperCase()); 108 _configureParameterValues(configuration.getChild("parameters")); 109 } 110 111 @Override 112 public String getId() 113 { 114 return _id; 115 } 116 117 @Override 118 public I18nizableText getLabel() 119 { 120 return _label; 121 } 122 123 @Override 124 public I18nizableText getDescription() 125 { 126 return _description; 127 } 128 129 @Override 130 public FireProcess getFireProcess() 131 { 132 return _fireProcess; 133 } 134 135 @Override 136 public String getCronExpression() 137 { 138 return _cronExpression; 139 } 140 141 @Override 142 public String getSchedulableId() 143 { 144 return _schedulableId; 145 } 146 147 @Override 148 public boolean isRemovable() 149 { 150 return _removable; 151 } 152 153 @Override 154 public boolean isModifiable() 155 { 156 return _modifiable; 157 } 158 159 @Override 160 public boolean isDeactivatable() 161 { 162 return _deactivatable; 163 } 164 165 @Override 166 public MisfirePolicy getMisfirePolicy() 167 { 168 return _misfirePolicy; 169 } 170 171 @Override 172 public boolean isVolatile() 173 { 174 // A configurable runnable is read every time the server restart, so it must be volatile 175 return true; 176 } 177 178 @Override 179 public Map<String, Object> getParameterValues() 180 { 181 return _parameterValues; 182 } 183 184 /** 185 * Configure the values of the parameters 186 * @param paramConfigs the configurations of the parameter values 187 * @throws ConfigurationException if an error occurs 188 */ 189 protected void _configureParameterValues(Configuration paramConfigs) throws ConfigurationException 190 { 191 _parameterValues = new HashMap<>(); 192 193 Schedulable schedulable = _schedulableEP.getExtension(_schedulableId); 194 Map<String, ElementDefinition> declaredParameters = schedulable.getParameters(); 195 196 for (String paramId : declaredParameters.keySet()) 197 { 198 Configuration paramConf = paramConfigs.getChild(paramId, false); 199 if (paramConf == null) 200 { 201 String message = String.format("The parameter '%s' is missing for the Runnable of id '%s'.", paramId, _id); 202 throw new ConfigurationException(message, paramConfigs); 203 } 204 else 205 { 206 String valueAsString = paramConf.getValue(""); 207 208 ElementDefinition definition = declaredParameters.get(paramId); 209 ElementType type = definition.getType(); 210 211 Object typedValue = type.castValue(valueAsString); 212 _parameterValues.put(paramId, typedValue); 213 } 214 } 215 } 216 217 @Override 218 public UserIdentity getUserIdentity() 219 { 220 return UserPopulationDAO.SYSTEM_USER_IDENTITY; 221 } 222}