package org.ovirt.engine.core.utils.timer; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * The JobWrapper gives 2 functionalities: 1. Enable running a method within an * instance. 2. Enable running more than one method within a Class as a * scheduled method. */ public class JobWrapper implements Job { // static data members private static Map<String, Method> cachedMethods = new HashMap<String, Method>(); private final Log log = LogFactory.getLog(SchedulerUtilQuartzImpl.class); /** * execute a method within an instance. The instance and the method name are * expected to be in the context given object. * * @param context * the context for this job. */ @SuppressWarnings("unchecked") @Override public void execute(JobExecutionContext context) throws JobExecutionException { String methodName = null; try { JobDataMap data = context.getJobDetail().getJobDataMap(); Map paramsMap = data.getWrappedMap(); methodName = (String) paramsMap.get(SchedulerUtilQuartzImpl.RUN_METHOD_NAME); Object instance = paramsMap.get(SchedulerUtilQuartzImpl.RUNNABLE_INSTANCE); // Class[] methodParamsType = // (Class[])paramsMap.get(SchedulerUtilQuartzImpl.RUN_METHOD_PARAM_TYPE); Object[] methodParams = (Object[]) paramsMap.get(SchedulerUtilQuartzImpl.RUN_METHOD_PARAM); String methodKey = getMethodKey(instance.getClass().getName(), methodName); Method methodToRun = cachedMethods.get(methodKey); if (methodToRun == null) { synchronized (cachedMethods) { if (cachedMethods.containsKey(methodToRun)) { methodToRun = cachedMethods.get(methodKey); } else { // methodToRun = // instance.getClass().getMethod(methodName,methodParamsType); methodToRun = getMethodToRun(instance, methodName); if (methodToRun == null) { log.error("could not find the required method " + methodName + " on instance of " + instance.getClass().getSimpleName()); return; } else { cachedMethods.put(methodKey, methodToRun); } } } } methodToRun.invoke(instance, methodParams); } catch (Exception e) { log.error("failed to invoke sceduled method " + methodName, e); JobExecutionException jee = new JobExecutionException("failed to execute job"); jee.setStackTrace(e.getStackTrace()); throw jee; } } /** * go over the class methods and find the method with the * OnTimerMethodAnnotation and the methodId * * @param instance * the instance of the class to look the methods on * @param methodId * the id of the method as stated in the OnTimerMethodAnnotation * annotation * @return the Method to run */ private Method getMethodToRun(Object instance, String methodId) { Method methodToRun = null; Method[] methods = instance.getClass().getMethods(); for (Method method : methods) { OnTimerMethodAnnotation annotation = method.getAnnotation(OnTimerMethodAnnotation.class); if (annotation != null && methodId.equals(annotation.value())) { methodToRun = method; break; } } return methodToRun; } /* * returns the key of the given method in the given class */ private String getMethodKey(String className, String methodName) { return className + "." + methodName; } }