Java tutorial
/* * This file is part of Cherry. * * Cherry is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cherry is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Cherry. If not, see <http://www.gnu.org/licenses/>. * */ package net.sheehantech.cherry.pool; import net.sheehantech.cherry.*; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class KeyedPooledPushClient<K> extends AbstractKeyedPushClient<K> { private Logger logger = LoggerFactory.getLogger(KeyedPooledPushClient.class); private GenericKeyedObjectPool<K, PooledPushSocket> pool; private Integer maxTotal; private Integer maxIdle; private Integer minIdle; private ExecutorService executor; public KeyedPooledPushClient(Map<K, SSLContext> sslContexts, Map<K, String> gateways, Map<K, Integer> ports) { super(sslContexts, gateways, ports); executor = Executors.newCachedThreadPool(); } public Integer getMaxTotal() { return maxTotal; } public void setMaxTotal(Integer maxTotal) { this.maxTotal = maxTotal; } public Integer getMaxIdle() { return maxIdle; } public void setMaxIdle(Integer maxIdle) { this.maxIdle = maxIdle; } public Integer getMinIdle() { return minIdle; } public void setMinIdle(Integer minIdle) { this.minIdle = minIdle; } @Override public void init() throws ConnectionFailedException { GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig(); if (maxTotal != null) config.setMaxTotalPerKey(maxTotal); if (maxIdle != null) config.setMaxIdlePerKey(maxIdle); if (minIdle != null) config.setMinIdlePerKey(minIdle); config.setTestOnBorrow(true); config.setTestWhileIdle(true); config.setBlockWhenExhausted(true); config.setMaxTotalPerKey(maxTotal); pool = new GenericKeyedObjectPool<K, PooledPushSocket>( new KeyedPooledPushSocketFactory(socketFactories, gateways, ports), config); try { for (K k : sslContexts.keySet()) pool.preparePool(k); } catch (Exception e) { throw (new ConnectionFailedException(e)); } logger.debug("Started new push socket pool with {} sockets", pool.getNumIdle()); } @Override public Future<PushResult> send(Notification notification) throws PushFailedException, ProtocolException { throw (new PushFailedException()); } @Override public KeyedNotificationBuilder<K> newNotification() { return null; } @Override public KeyedNotificationBuilder<K> newNotification(K k) { return (new KeyedNotificationBuilder<K>(this, k)); } @Override public Future<PushResult> send(Notification notification, K k) throws PushFailedException, ProtocolException { try { notification.setId(nextId()); Future<PushResult> pushResultFuture = executor .submit(new KeyedPooledSendNotificationTask(pool, k, notification)); logger.debug("Sent notification {}", notification.getId()); return pushResultFuture; } catch (Exception e) { throw (new PushFailedException(e)); } } @Override public void shutdown() { while (!pool.isClosed()) { if (pool.getNumActive() == 0) { pool.close(); logger.info("Shut down pool"); } else { try { logger.debug("Waiting for {} active sockets", pool.getNumActive()); Thread.sleep(100); } catch (InterruptedException e) { logger.debug("Interrrupted during graceful shutdown"); } } } } @Override public void shutdownNow() { pool.close(); } }