package org.kevoree.core; import org.kevoree.api.handler.ModelListener; import org.kevoree.api.handler.UpdateContext; import org.kevoree.api.telemetry.TelemetryEvent; import org.kevoree.log.Log; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; public class KevoreeListeners { private KevoreeCoreBean core; private ExecutorService scheduler = null; private ExecutorService schedulerAsync = null; private List<ModelListener> registeredListeners = new ArrayList<ModelListener>(); public KevoreeListeners(KevoreeCoreBean core) { this.core = core; } public void start(String nodeName) { scheduler = java.util.concurrent.Executors.newSingleThreadExecutor(new KL_ThreadFactory(nodeName)); schedulerAsync = java.util.concurrent.Executors.newCachedThreadPool(new KL_ThreadFactory2(nodeName)); } public void addListener(ModelListener l) { if (scheduler != null) { scheduler.submit(new AddListener(l)); } } public void removeListener(ModelListener l) { if (scheduler != null) { scheduler.submit(new RemoveListener(l)); } } public void notifyAllListener() { if (scheduler != null) { scheduler.submit(new NotifyAllListener()); } } public void stop() { registeredListeners.clear(); if (schedulerAsync != null) { schedulerAsync.shutdownNow(); } schedulerAsync = null; if (scheduler != null) { scheduler.shutdownNow(); } scheduler = null; } public boolean initUpdate(final UpdateContext context) { try { if (scheduler != null) { return scheduler.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { for (ModelListener listener : registeredListeners) { boolean result = listener.initUpdate(context); if (!result) { return false; } } return true; } }).get(); } else { return true; } } catch (Exception e) { return false; } } public boolean preUpdate(final UpdateContext context) { try { if (scheduler != null) { return scheduler.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { for (ModelListener listener : registeredListeners) { boolean result = listener.preUpdate(context); if (!result) { return false; } } return true; } }).get(); } else { return true; } } catch (Exception e) { return false; } } public boolean afterUpdate(final UpdateContext context) { try { if (scheduler != null) { return scheduler.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { for (ModelListener listener : registeredListeners) { boolean result = listener.afterLocalUpdate(context); if (!result) { return false; } } return true; } }).get(); } else { return true; } } catch (Exception e) { return false; } } public void preRollback(final UpdateContext context) { if (scheduler != null) { scheduler.submit(new Runnable() { @Override public void run() { for (ModelListener listener : registeredListeners) { listener.preRollback(context); } } }); } } public void postRollback(final UpdateContext context) { if (scheduler != null) { scheduler.submit(new Runnable() { @Override public void run() { for (ModelListener listener : registeredListeners) { listener.postRollback(context); } } }); } } private class AddListener implements Runnable { private ModelListener listener; public AddListener(ModelListener listener) { this.listener = listener; } @Override public void run() { if (!registeredListeners.contains(listener)) { registeredListeners.add(listener); } } } private class RemoveListener implements Runnable { private ModelListener listener; public RemoveListener(ModelListener listener) { this.listener = listener; } @Override public void run() { if (registeredListeners.contains(listener)) { registeredListeners.remove(listener); } } } private class NotifyAllListener implements Runnable { @Override public void run() { for (ModelListener listener : registeredListeners) { if (schedulerAsync != null) { schedulerAsync.submit(new NotifyListener(listener)); } } } } private class NotifyListener implements Runnable { private ModelListener listener; public NotifyListener(ModelListener listener) { this.listener = listener; } @Override public void run() { try { Thread.currentThread().setContextClassLoader(listener.getClass().getClassLoader()); listener.modelUpdated(); } catch (Exception e) { core.broadcastTelemetry(TelemetryEvent.Type.LOG_ERROR, "Error while triggering modelUpdated() listener method", e); Log.error("Error while triggering modelUpdated() listener method", e); } } } private class KL_ThreadFactory implements ThreadFactory { private String name; private SecurityManager manager = System.getSecurityManager(); private ThreadGroup group; public KL_ThreadFactory(String name) { this.name = name; this.manager = System.getSecurityManager(); if (this.manager != null) { this.group = this.manager.getThreadGroup(); } else { this.group = Thread.currentThread().getThreadGroup(); } } @Override public Thread newThread(Runnable runnable) { Thread t = new Thread(group, runnable, "Kevoree_ListenerScheduler_" + name); if (t.isDaemon()) { t.setDaemon(false); } if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } return t; } } private class KL_ThreadFactory2 implements ThreadFactory { private String name; private AtomicInteger numCreated; private SecurityManager manager = System.getSecurityManager(); private ThreadGroup group; public KL_ThreadFactory2(String name) { this.name = name; this.numCreated = new AtomicInteger(); this.manager = System.getSecurityManager(); if (this.manager != null) { this.group = this.manager.getThreadGroup(); } else { this.group = Thread.currentThread().getThreadGroup(); } } @Override public Thread newThread(Runnable runnable) { Thread t = new Thread(group, runnable, "Kevoree_AsyncListenerScheduler_" + name + "_" + numCreated.getAndIncrement()); if (t.isDaemon()) { t.setDaemon(false); } if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } return t; } } }