/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.eas.server; import com.eas.client.ModulesProxy; import com.eas.client.ScriptedDatabasesClient; import com.eas.client.SqlQuery; import com.eas.client.cache.ApplicationSourceIndexer; import com.eas.client.cache.ScriptsConfigs; import com.eas.client.queries.QueriesProxy; import com.eas.concurrent.PlatypusThreadFactory; import com.eas.sensors.api.RetranslateFactory; import com.eas.sensors.api.SensorsFactory; import com.eas.server.mina.platypus.PlatypusRequestsHandler; import com.eas.server.mina.platypus.RequestDecoder; import com.eas.server.mina.platypus.ResponseEncoder; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.SSLContext; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.nio.NioProcessor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; /** * * @author pk, mg refactoring */ public class PlatypusServer extends PlatypusServerCore { public final static int DEFAULT_PORT = 8500; public final static String DEFAULT_PROTOCOL = "platypus"; protected SSLContext sslContext; public final static String HTTP_PROTOCOL = "http"; public final static String HTTPS_PROTOCOL = "https"; public final static int DEFAULT_EXECUTOR_POOL_SIZE = Runtime.getRuntime().availableProcessors() + 1; private final SensorsFactory acceptorsFactory; private final RetranslateFactory retranslateFactory; private final InetSocketAddress[] listenAddresses; private final Map<Integer, String> portsProtocols; private final Map<Integer, Integer> portsSessionIdleTimeouts; private final Map<Integer, Integer> portsSessionIdleCheckIntervals; private final Executor executor; public PlatypusServer(ApplicationSourceIndexer aIndexer, ModulesProxy aModules, QueriesProxy<SqlQuery> aQueries, ScriptedDatabasesClient aDatabasesClient, SSLContext aSslContext, InetSocketAddress[] aAddresses, Map<Integer, String> aPortsProtocols, Map<Integer, Integer> aPortsSessionIdleTimeouts, Map<Integer, Integer> aPortsSessionIdleCheckInterval, Executor aExecutor, ScriptsConfigs aScriptsConfigs, String aDefaultAppElement) throws Exception { super(aIndexer, aModules, aQueries, aDatabasesClient, aScriptsConfigs, aDefaultAppElement); if (aAddresses == null) { throw new NullPointerException("listenAddresses is null"); } else if (aAddresses.length == 0) { throw new IllegalArgumentException("listenAddresses is empty"); } executor = aExecutor; listenAddresses = aAddresses; portsProtocols = aPortsProtocols; portsSessionIdleTimeouts = aPortsSessionIdleTimeouts; portsSessionIdleCheckIntervals = aPortsSessionIdleCheckInterval; sslContext = aSslContext; acceptorsFactory = obtainAcceptorsFactory(); retranslateFactory = obtainRetranslateFactory(); } @Override public Type getType() { return Type.TSA; } public void start(Set<String> aResidents, Map<String, String> aAcceptors) throws Exception { //instance = this;// Hack, but server is natural singleton and so it is ok. for (InetSocketAddress s : listenAddresses) { initializeAndBindAcceptor(s, aAcceptors, executor); } assert listenAddresses != null : "listenAddresses != null"; assert listenAddresses.length > 0 : "listenAddresses.length > 0"; } private void tryToInitializeAndBindSensorAcceptor(String protocol, InetSocketAddress s, Map<String, String> aAcceptors, Executor aExecutor) throws IOException, Exception { if (acceptorsFactory != null && acceptorsFactory.isSupported(protocol)) { String acceptorModuleName = aAcceptors.get(protocol); if (acceptorModuleName == null) { acceptorModuleName = aAcceptors.get(null); } if (acceptorModuleName != null) { Integer sessionIdleTime = portsSessionIdleTimeouts != null ? portsSessionIdleTimeouts.get(s.getPort()) : null; if (sessionIdleTime == null || sessionIdleTime == 0) { sessionIdleTime = 360; } Integer sessionIdleCheckInterval = portsSessionIdleCheckIntervals != null ? portsSessionIdleCheckIntervals.get(s.getPort()) : null; if (sessionIdleCheckInterval == null || sessionIdleCheckInterval == 0) { sessionIdleCheckInterval = 360; } IoAcceptor sensorAcceptor = acceptorsFactory.create(protocol, aExecutor, sessionIdleTime, sessionIdleCheckInterval, new com.eas.server.handlers.PositioningPacketReciever(this, acceptorModuleName, retranslateFactory)); if (sensorAcceptor != null) { sensorAcceptor.bind(s); Logger.getLogger(PlatypusServer.class.getName()).log(Level.INFO, "Listening {0} protocol on {1}", new Object[]{protocol, s.toString()}); } } else { Logger.getLogger(PlatypusServer.class.getName()).log(Level.INFO, "Acceptor module was not found for {0} protocol", protocol); } } else { Logger.getLogger(PlatypusServer.class.getName()).log(Level.INFO, "{0} protocol is not supported", protocol); } } private void initializeAndBindAcceptor(InetSocketAddress s, Map<String, String> aAcceptors, Executor aExecutor) throws IOException, Exception { // archive protocol for address String protocol = DEFAULT_PROTOCOL; if (portsProtocols.containsKey(s.getPort())) { protocol = portsProtocols.get(s.getPort()); } // initialize acceptor according to protocol if (DEFAULT_PROTOCOL.equalsIgnoreCase(protocol)) { initializeAndBindPlatypusAcceptor(s); } else { tryToInitializeAndBindSensorAcceptor(protocol, s, aAcceptors, aExecutor); } } private void initializeAndBindPlatypusAcceptor(InetSocketAddress s) throws IOException, Exception { //final SslFilter sslFilter = new SslFilter(sslContext); commented out until MINA Sslfilter bugs will be fixed ThreadPoolExecutor connectionsPollerExecutor = new ThreadPoolExecutor(1, 1, 3L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new PlatypusThreadFactory("nio-polling-", false)); final IoAcceptor acceptor = new NioSocketAcceptor(connectionsPollerExecutor, new NioProcessor(executor)); //acceptor.getFilterChain().addLast("encryption", sslFilter); commented out until MINA Sslfilter bugs will be fixed acceptor.getFilterChain().addLast("platypusCodec", new ProtocolCodecFilter(new ResponseEncoder(), new RequestDecoder())); /* acceptor.getFilterChain().addLast("executor", new ExecutorFilter(executor, IoEventType.EXCEPTION_CAUGHT, IoEventType.MESSAGE_RECEIVED, IoEventType.MESSAGE_SENT, IoEventType.SESSION_CLOSED, IoEventType.SESSION_IDLE, IoEventType.CLOSE, IoEventType.WRITE)); */ PlatypusRequestsHandler handler = new PlatypusRequestsHandler(this); acceptor.setHandler(handler); Integer sessionIdleTime = portsSessionIdleTimeouts != null ? portsSessionIdleTimeouts.get(s.getPort()) : null; if (sessionIdleTime == null || sessionIdleTime == 0) { sessionIdleTime = PlatypusRequestsHandler.SESSION_TIME_OUT; } Integer sessionIdleCheckInterval = portsSessionIdleCheckIntervals != null ? portsSessionIdleCheckIntervals.get(s.getPort()) : null; if (sessionIdleCheckInterval == null || sessionIdleCheckInterval == 0) { sessionIdleCheckInterval = PlatypusRequestsHandler.IDLE_TIME_EVENT; } handler.setSessionIdleCheckInterval(sessionIdleCheckInterval); handler.setSessionIdleTime(sessionIdleTime); acceptor.bind(s); Logger.getLogger(ServerMain.class.getName()).log(Level.INFO, "Listening platypus protocol on {0}", s.toString()); } private SensorsFactory obtainAcceptorsFactory() { SensorsFactory recieveFactory = null; try { Class<SensorsFactory> acceptorsFactoryClass = (Class<SensorsFactory>) Class.forName("com.eas.sensors.AcceptorsFactory"); recieveFactory = acceptorsFactoryClass.newInstance(); } catch (ClassNotFoundException e) { Logger.getLogger(PlatypusServer.class.getName()).log(Level.INFO, "Sensors acceptors are not on the classpath."); } catch (InstantiationException | IllegalAccessException ex) { Logger.getLogger(PlatypusServer.class.getName()).log(Level.SEVERE, null, ex); } return recieveFactory; } private RetranslateFactory obtainRetranslateFactory() { RetranslateFactory factory = null; try { Class<RetranslateFactory> retranslateFactoryClass = (Class<RetranslateFactory>) Class.forName("com.eas.sensors.ConnectorsFactory"); factory = retranslateFactoryClass.getConstructor(new Class<?>[]{Map.class}).newInstance(DEFAULT_EXECUTOR_POOL_SIZE); } catch (ClassNotFoundException e) { Logger.getLogger(PlatypusServer.class.getName()).info("Sensors retranslators are not on the classpath."); } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { Logger.getLogger(PlatypusServer.class.getName()).log(Level.SEVERE, null, ex); } return factory; } public SensorsFactory getAcceptorsFactory() { return acceptorsFactory; } public RetranslateFactory getRetranslateFactory() { return retranslateFactory; } }