package act.job; /*- * #%L * ACT Framework * %% * Copyright (C) 2014 - 2017 ActFramework * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import act.app.App; import act.app.AppHolderBase; import act.app.event.AppEventId; import act.job.bytecode.ReflectedJobInvoker; import act.job.meta.JobClassMetaInfo; import act.job.meta.JobMethodMetaInfo; import org.osgl.$; import org.osgl.util.E; import org.osgl.util.S; import java.lang.annotation.Annotation; import java.util.List; public class JobAnnotationProcessor extends AppHolderBase<JobAnnotationProcessor> { private AppJobManager manager; public JobAnnotationProcessor(App app) { super(app); manager = app.jobManager(); } public void register(final JobMethodMetaInfo method, final Class<? extends Annotation> anno, final Object v) { if (isAbstract(method)) { app().jobManager().on(AppEventId.SINGLETON_PROVISIONED, new Runnable() { @Override public void run() { List<JobMethodMetaInfo> list = method.extendedJobMethodMetaInfoList(app()); for (JobMethodMetaInfo subMethodInfo : list) { register(subMethodInfo, anno, v); } } }); return; } _Job job = createMethodJob(method); if (Cron.class.isAssignableFrom(anno)) { registerCron(job, evaluateExpression(v.toString(), anno)); } else if (AlongWith.class.isAssignableFrom(anno)) { registerAlongWith(job, v.toString()); } else if (Every.class.isAssignableFrom(anno)) { registerEvery(job, evaluateExpression(v.toString(), anno)); } else if (FixedDelay.class.isAssignableFrom(anno)) { registerFixedDelay(job, evaluateExpression(v.toString(), anno)); } else if (InvokeAfter.class.isAssignableFrom(anno)) { registerInvokeAfter(job, v.toString()); } else if (InvokeBefore.class.isAssignableFrom(anno)) { registerInvokeBefore(job, v.toString()); } else if (OnAppStart.class.isAssignableFrom(anno)) { boolean async = null == v ? false : (Boolean)v; registerOnAppStart(job, async); } else if (OnAppStop.class.isAssignableFrom(anno)) { boolean async = null == v ? false : (Boolean) v; registerOnAppStop(job, async); } else if (OnAppEvent.class.isAssignableFrom(anno)) { boolean async = false; AppEventId appEventId; if (v instanceof $.T2) { $.T2<AppEventId, Boolean> t2 = $.cast(v); appEventId = t2._1; async = t2._2; } else { appEventId = $.cast(v); } registerOnAppEvent(job, appEventId, async); } else { throw E.unsupport("Unknown job annotation class: %s", anno.getName()); } } private String evaluateExpression(String expression, Class<? extends Annotation> annoClass) { String prefix = annoClass.getSimpleName(); if (S.eq(FixedDelay.class.getName(), prefix)) { prefix = "fixed-delay"; } else { prefix = prefix.toLowerCase(); } String ret = expression.trim(); if (ret.startsWith(prefix)) { ret = (String) app().config().get(expression); if (S.blank(ret)) { throw E.invalidConfiguration("Expression configuration not found: %s", expression); } } return ret; } private void registerCron(_Job job, String expression) { JobTrigger.cron(expression).register(job, manager); } private void registerAlongWith(_Job job, String targetJobId) { JobTrigger.alongWith(targetJobId).register(job, manager); } private void registerEvery(_Job job, String expression) { JobTrigger.every(expression).register(job, manager); } private void registerFixedDelay(_Job job, String expression) { JobTrigger.fixedDelay(expression).register(job, manager); } private void registerInvokeAfter(_Job job, String targetJobId) { JobTrigger.after(targetJobId).register(job, manager); } private void registerInvokeBefore(_Job job, String targetJobId) { JobTrigger.before(targetJobId).register(job, manager); } private void registerOnAppStart(_Job job, boolean async) { JobTrigger.onAppStart(async).register(job, manager); } private void registerOnAppStop(_Job job, boolean async) { JobTrigger.onAppStop(async).register(job, manager); } private void registerOnAppEvent(_Job job, AppEventId appEventId, boolean async) { JobTrigger.onAppEvent(appEventId, async).register(job, manager); } private boolean isAbstract(JobMethodMetaInfo method) { JobClassMetaInfo classMetaInfo = method.classInfo(); return (classMetaInfo.isAbstract()); } private _Job createMethodJob(JobMethodMetaInfo method) { String id = method.id(); return new _Job(id, app().jobManager(), new ReflectedJobInvoker<>(method, app()), false); } }