001/* 002 * Stallion Core: A Modern Web Framework 003 * 004 * Copyright (C) 2015 - 2016 Stallion Software LLC. 005 * 006 * This program is free software: you can redistribute it and/or modify it under the terms of the 007 * GNU General Public License as published by the Free Software Foundation, either version 2 of 008 * the License, or (at your option) any later version. This program is distributed in the hope that 009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 011 * License for more details. You should have received a copy of the GNU General Public License 012 * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. 013 * 014 * 015 * 016 */ 017 018package io.stallion.asyncTasks; 019 020import io.stallion.plugins.StallionJavaPlugin; 021import io.stallion.plugins.PluginRegistry; 022import io.stallion.plugins.javascript.JsAsyncTaskHandler; 023import io.stallion.services.Log; 024import io.stallion.utils.json.JSON; 025 026import java.util.HashMap; 027import java.util.Map; 028 029import static io.stallion.utils.Literals.empty; 030 031public class AsyncTaskExecuteRunnable implements Runnable { 032 033 private Boolean triggerShutdown = false; 034 private AsyncTask task; 035 private static final Map<String, Class> classCache = new HashMap<>(); 036 037 public AsyncTaskExecuteRunnable(AsyncTask task) { 038 this.task = task; 039 } 040 041 public static void registerClass(String name, Class<? extends AsyncTaskHandler> cls) { 042 classCache.put(name, cls); 043 } 044 045 @Override 046 public void run() { 047 run(false); 048 } 049 050 051 052 public void run(boolean synchronousMode) { 053 try { 054 Log.info("Executing task: {0}", task.getId()); 055 056 Class cls = lookupClass(task.getHandlerName()); 057 Log.info("Loaded async handler class: {0}", cls.getName()); 058 AsyncTaskHandler handler = (AsyncTaskHandler)JSON.parse(task.getDataJson(), cls); 059 if (handler instanceof JsAsyncTaskHandler && !empty(task.getDataJson())) { 060 ((JsAsyncTaskHandler)handler).putAll(JSON.parseMap(task.getDataJson())); 061 } 062 handler.setTask(task); 063 handler.process(); 064 AsyncCoordinator.instance().markCompleted(task); 065 } catch(Exception e) { 066 if (synchronousMode) { 067 throw new RuntimeException(e); 068 } 069 String dump = ""; 070 try { 071 dump = JSON.stringify(task); 072 } catch (Exception e1) { 073 } 074 Log.exception(e, "Exception processing task id:{0} handler:{1} customKey:{2} dump:{3}", 075 task.getId(), task.getHandlerName(), task.getCustomKey(), dump); 076 try { 077 AsyncCoordinator.instance().markFailed(task, e); 078 if (task.getTryCount() < 5) { 079 Log.info("Adding task back into the queue {0}", task.getId()); 080 ((AsyncFileCoordinator)AsyncCoordinator.instance()).getTaskQueue().add(task); 081 } 082 } catch (Exception persistException) { 083 Log.exception(persistException, "Exception persisting task changes for id:{0}", task.getId()); 084 } 085 } 086 } 087 088 private Class lookupClass(String className) throws ClassNotFoundException { 089 if (classCache.containsKey(className)) { 090 return classCache.get(className); 091 } 092 Class cls = null; 093 094 try { 095 cls = getClass().getClassLoader().loadClass(task.getHandlerName()); 096 } catch (ClassNotFoundException e) { 097 098 } 099 if (cls != null) { 100 classCache.put(className, cls); 101 } 102 for (StallionJavaPlugin booter: PluginRegistry.instance().getJavaPluginByName().values()) { 103 try { 104 cls = booter.getClass().getClassLoader().loadClass(task.getHandlerName()); 105 if (cls != null) { 106 classCache.put(className, cls); 107 return cls; 108 } 109 } catch (ClassNotFoundException e) { 110 111 } 112 } 113 for (ClassLoader loader: AsyncCoordinator.instance().getExtraClassLoaders()) { 114 try { 115 cls = loader.loadClass(task.getHandlerName()); 116 if (cls != null) { 117 classCache.put(className, cls); 118 return cls; 119 } 120 } catch (ClassNotFoundException e) { 121 122 } 123 } 124 throw new ClassNotFoundException("Class not found: " + className); 125 } 126 127 128 public Boolean getTriggerShutdown() { 129 return triggerShutdown; 130 } 131 132 public void setTriggerShutdown(Boolean triggerShutdown) { 133 this.triggerShutdown = triggerShutdown; 134 } 135 136}