Java tutorial
/* * Copyright 2013 DiscoveryBay Inc. * * 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. */ package com.jiangge.apns4j.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.net.SocketFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import static com.jiangge.apns4j.model.ApnsConstants.*; import com.jiangge.apns4j.IApnsConnection; import com.jiangge.apns4j.IApnsFeedbackConnection; import com.jiangge.apns4j.IApnsService; import com.jiangge.apns4j.model.ApnsConfig; import com.jiangge.apns4j.model.Feedback; import com.jiangge.apns4j.model.Payload; import com.jiangge.apns4j.model.PushNotification; import com.jiangge.apns4j.tools.ApnsTools; /** * The service should be created twice at most. One for the development env, and the other for the production env * @author RamosLi * */ public class ApnsServiceImpl implements IApnsService { private static Log logger = LogFactory.getLog(ApnsServiceImpl.class); private ExecutorService service = null; private ApnsConnectionPool connPool = null; private IApnsFeedbackConnection feedbackConn = null; private ApnsServiceImpl(ApnsConfig config) { int poolSize = config.getPoolSize(); service = Executors.newFixedThreadPool(poolSize); SocketFactory factory = ApnsTools.createSocketFactory(config.getKeyStore(), config.getPassword(), KEYSTORE_TYPE, ALGORITHM, PROTOCOL); connPool = ApnsConnectionPool.newConnPool(config, factory); feedbackConn = new ApnsFeedbackConnectionImpl(config, factory); } @Override public void sendNotification(final String token, final Payload payload) { service.execute(new Runnable() { @Override public void run() { IApnsConnection conn = null; try { conn = getConnection(); conn.sendNotification(token, payload); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (conn != null) { connPool.returnConn(conn); } } } }); } @Override public void sendNotification(final PushNotification notification) { service.execute(new Runnable() { @Override public void run() { IApnsConnection conn = null; try { conn = getConnection(); conn.sendNotification(notification); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (conn != null) { connPool.returnConn(conn); } } } }); } private IApnsConnection getConnection() { IApnsConnection conn = connPool.borrowConn(); if (conn == null) { throw new RuntimeException("Can't get apns connection"); } return conn; } private static void checkConfig(ApnsConfig config) { if (config == null || config.getKeyStore() == null || config.getPassword() == null || "".equals(config.getPassword().trim())) { throw new IllegalArgumentException("KeyStore and password can't be null"); } if (config.getPoolSize() <= 0 || config.getRetries() <= 0 || config.getCacheLength() <= 0) { throw new IllegalArgumentException("poolSize,retry, cacheLength must be positive"); } } private static Map<String, IApnsService> serviceCacheMap = new HashMap<String, IApnsService>(3); public static IApnsService getCachedService(String name) { return serviceCacheMap.get(name); } public static IApnsService createInstance(ApnsConfig config) { checkConfig(config); String name = config.getName(); IApnsService service = getCachedService(name); if (service == null) { synchronized (name.intern()) { service = getCachedService(name); if (service == null) { service = new ApnsServiceImpl(config); serviceCacheMap.put(name, service); } } } return service; } @Override public void shutdown() { service.shutdown(); try { service.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { logger.warn("Shutdown ApnsService interrupted", e); } connPool.close(); } @Override public List<Feedback> getFeedbacks() { return feedbackConn.getFeedbacks(); } }