package com.aincc.lib.network; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Map.Entry; import java.util.Queue; import java.util.Set; import java.util.concurrent.RejectedExecutionException; import com.aincc.lib.network.common.BaseTask; import com.aincc.lib.network.common.BaseTrans; import com.aincc.lib.network.common.BaseTransEx; import com.aincc.lib.network.common.INetworkListener; import com.aincc.lib.network.common.NetworkErrorType; import com.aincc.lib.network.http.HttpTask; import com.aincc.lib.network.http.HttpTrans; /** * * <h3><b>NetworkProcessor</b></h3></br> * * network processor * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ public class NetHttpProcessor { /** * error message mapping list * * @since 1.0.0 */ private static HashMap<Integer, NetworkErrorType> errorMap = new HashMap<Integer, NetworkErrorType>(); /** * processor * * @since 1.0.0 */ private volatile static NetHttpProcessor processor; /** * max concurrent task count * * @since 1.0.0 */ private static final int MAX_CONCURRENT = 10; /** * max task sequence * * @since 1.0.0 */ private static final int MAX_TASK_SEQ = 65536; /** * invalid sequence * * @since 1.0.0 */ public static final int INVALID_UNI_SEQ = -1; /** * task sequence * * @since 1.0.0 */ private static int taskSeq = 0; /** * running task count * * @since 1.0.0 */ private int runningCount = 0; /** * running task * * @since 1.0.0 */ private Hashtable<Integer, BaseTask<?>> runningTask = null; /** * delayed task * * @since 1.0.0 */ private Queue<BaseTask<?>> delayedTask = null; /** * regist message for specific error type * * @since 1.0.0 * @param type * @param message */ public static void registerErrorMessage(NetworkErrorType type, String message) { if (null != message) { type.setMessage(message); } errorMap.put(type.getType(), type); } /** * * @since 1.0.0 * @param type * @return NetworkErrorType */ public static NetworkErrorType getErrorMessage(NetworkErrorType type) { if (errorMap.containsKey(type.getType())) { return errorMap.get(type.getMessage()); } return NetworkErrorType.UNKNOWN_ERROR; } /** * * @since 1.0.0 */ public static NetHttpProcessor getInstance() { if (null == processor) { synchronized (NetHttpProcessor.class) { if (null == processor) { processor = new NetHttpProcessor(); } } } return processor; } /** * send transaction (for http) * * @since 1.0.0 * @param serviceUrl * @param listener * @param task */ public void sendHttp(String serviceUrl, INetworkListener listener, HttpTask<?, ?> task) { task.setListener(listener); task.setProcessor(processor); ((HttpTrans) task.getTr()).setServiceUri(serviceUrl); processor.send(task); } /** * cancel all * * @since 1.0.0 */ public void cancelAll() { processor.cancel(); } /** * private constructor * * @since 1.0.0 */ private NetHttpProcessor() { if (null == runningTask) { runningTask = new Hashtable<Integer, BaseTask<?>>(); } if (null == delayedTask) { delayedTask = new LinkedList<BaseTask<?>>(); } } /** * send transaction * * @since 1.0.0 * @param task */ private void send(HttpTask<?, ?> task) { synchronized (this) { try { taskSeq = (taskSeq + 1) % MAX_TASK_SEQ; task.setTaskSeq(taskSeq); if (runningCount >= MAX_CONCURRENT) { delayedTask.add(task); } else { runningCount++; runningTask.put(task.getTaskSeq(), task); task.execute(); } } catch (RejectedExecutionException e) { e.printStackTrace(); task.getListener().iNetRejectedExecution(new BaseTransEx(getErrorMessage(NetworkErrorType.ERROR_SEND).toString(), ((BaseTrans) task.getTr()).getParam())); } } } /** * * @since 1.0.0 */ private void cancel() { synchronized (this) { delayedTask.clear(); Set<Entry<Integer, BaseTask<?>>> entrySet = runningTask.entrySet(); Iterator<Entry<Integer, BaseTask<?>>> it = entrySet.iterator(); while (it.hasNext()) { Entry<Integer, BaseTask<?>> entry = it.next(); BaseTask<?> task = entry.getValue(); if (null != task && task.isRunning()) { task.cancel(true); } } runningTask.clear(); runningCount = 0; } } /** * * @since 1.0.0 * @param completeTaskKey */ public void nextTask(int completeTaskKey) { synchronized (this) { if (runningTask.containsKey(completeTaskKey)) { runningTask.remove(completeTaskKey); } if (runningCount > 0) { runningCount--; if (!delayedTask.isEmpty()) { processor.send((HttpTask<?, ?>) delayedTask.poll()); } } } } }