/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.inject.lifecycle; import org.eclipse.che.commons.schedule.Launcher; import org.eclipse.che.commons.schedule.ScheduleCron; import org.eclipse.che.commons.schedule.ScheduleDelay; import org.eclipse.che.commons.schedule.ScheduleRate; import org.eclipse.che.commons.schedule.executor.LoggedRunnable; import com.google.inject.ConfigurationException; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.matcher.Matcher; import com.google.inject.matcher.Matchers; import com.google.inject.name.Names; import com.google.inject.spi.InjectionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; /** * Listen guice injections and launch method marked with schedule annotations. * * @author Sergii Kabashniuk */ public class ScheduleInjectionListener<T> extends LifecycleModule implements InjectionListener<T> { private static final Logger LOG = LoggerFactory.getLogger(ScheduleInjectionListener.class); private final Matcher<AnnotatedElement> javaxSingleton = Matchers.annotatedWith(javax.inject.Singleton.class); private final Matcher<AnnotatedElement> googleSingleton = Matchers.annotatedWith(com.google.inject.Singleton.class); private final Provider<Launcher> launcherProvider; private final Provider<Injector> injectorProvider; public ScheduleInjectionListener(Provider<Launcher> launcherProvider, Provider<Injector> injectorProvider) { this.launcherProvider = launcherProvider; this.injectorProvider = injectorProvider; } private <T> T getValue(Class<T> configurationType, String configurationKey) { try { return injectorProvider.get().getInstance(Key.get(configurationType, Names.named(configurationKey))); } catch (ConfigurationException | ProvisionException e) { return null; } } private long getValue(String configurationKey) { String stringValue = getValue(String.class, configurationKey); if (stringValue != null) { long result = Long.parseLong(stringValue); if (result == 0) { throw new RuntimeException("Invalid value 0 for parameter " + configurationKey); } return result; } Long longValue = getValue(Long.class, configurationKey); if (longValue != null) { long result = longValue.longValue(); if (result == 0) { throw new RuntimeException("Invalid value 0 for parameter " + configurationKey); } return result; } Integer intValue = getValue(Integer.class, configurationKey); if (intValue != null) { long result = intValue.longValue(); if (result == 0) { throw new RuntimeException("Invalid value 0 for parameter " + configurationKey); } return result; } throw new RuntimeException("Parameter " + configurationKey + " is not configured"); } private void launch(Object object, Method method, ScheduleCron annotation) { Launcher launcher = launcherProvider.get(); launcher.scheduleCron(new LoggedRunnable(object, method), annotation.cronParameterName().isEmpty() ? annotation.cron() : getValue(String.class, annotation .cronParameterName ())); } private void launch(Object object, Method method, ScheduleDelay annotation) { if (annotation.delayParameterName().isEmpty() && annotation.delay() == 0) { throw new RuntimeException("Delay parameter is not configured"); } Launcher launcher = launcherProvider.get(); launcher.scheduleWithFixedDelay(new LoggedRunnable(object, method), annotation.initialDelayParameterName().isEmpty() ? annotation.initialDelay() : getValue( annotation .initialDelayParameterName()), annotation.delayParameterName().isEmpty() ? annotation.delay() : getValue( annotation.delayParameterName()), annotation.unit()); } private void launch(Object object, Method method, ScheduleRate annotation) { if (annotation.periodParameterName().isEmpty() && annotation.period() == 0) { throw new RuntimeException("Period parameter is not configured"); } Launcher launcher = launcherProvider.get(); launcher.scheduleAtFixedRate(new LoggedRunnable(object, method), annotation.initialDelayParameterName().isEmpty() ? annotation.initialDelay() : getValue( annotation .initialDelayParameterName()), annotation.periodParameterName().isEmpty() ? annotation.period() : getValue( annotation.periodParameterName()), annotation.unit()); } private void launch(Object object, Class<? extends Annotation> annotationType) { boolean isSingleton = javaxSingleton.matches(object.getClass()) || googleSingleton.matches(object.getClass()); for (Method method : get(object.getClass(), annotationType)) { if (!isSingleton) { throw new RuntimeException( "Scheduled class " + object.getClass() + " should be marked as singleton"); } if (annotationType.equals(ScheduleRate.class)) { launch(object, method, method.getAnnotation(ScheduleRate.class)); } else if (annotationType.equals(ScheduleDelay.class)) { launch(object, method, method.getAnnotation(ScheduleDelay.class)); } else if (annotationType.equals(ScheduleCron.class)) { launch(object, method, method.getAnnotation(ScheduleCron.class)); } } } @Override public void afterInjection(T injectee) { launch(injectee, ScheduleCron.class); launch(injectee, ScheduleRate.class); launch(injectee, ScheduleDelay.class); } @Override protected void configure() { } }