/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.notification;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.notification.common.Notification;
import org.geoserver.notification.common.NotificationProcessor;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
/**
*
* @author Xandros
*
*/
public class MessageProcessor {
private Logger LOGGER = Logging.getLogger(MessageProcessor.class);
private ThreadPoolExecutor executorPool;
private NotificationProcessor processor;
private Filter filter;
public void process(Notification notification) {
if (this.filter == null || this.filter.evaluate(notification)) {
executorPool.execute(new WorkerThread(notification, this.processor));
}
}
public MessageProcessor(int queueSize, int processorThreads, String filter,
NotificationProcessor processor) {
try {
if (filter != null && !filter.isEmpty()) {
this.filter = CQL.toFilter(filter);
}
} catch (CQLException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
this.processor = processor;
// Get the ThreadFactory implementation to use
ThreadFactory threadFactory = Executors.defaultThreadFactory();
// creating the ThreadPoolExecutor
executorPool = new ThreadPoolExecutor(1, processorThreads, 10, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(queueSize), threadFactory,
new RejectedExecutionHandlerImpl());
}
private class WorkerThread implements Runnable {
private Logger LOGGER = Logging.getLogger(WorkerThread.class);
private NotificationProcessor processor;
private Notification notification;
public WorkerThread(Notification notification, NotificationProcessor processor) {
this.processor = processor;
this.notification = notification;
}
@Override
public void run() {
try {
this.processor.process(this.notification);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
}
// RejectedExecutionHandler implementation
private class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
private Logger LOGGER = Logging.getLogger(RejectedExecutionHandlerImpl.class);
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
executor.execute(r);
}
}
}