/** * */ package com.trendrr.strest.server; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.execution.ExecutionHandler; import org.jboss.netty.handler.execution.MemoryAwareThreadPoolExecutor; import org.yaml.snakeyaml.Yaml; import com.trendrr.oss.DynMap; import com.trendrr.oss.DynMapFactory; import com.trendrr.oss.FileHelper; import com.trendrr.oss.Reflection; import com.trendrr.oss.SSLContextBuilder; import com.trendrr.strest.flash.FlashSocketPolicyServer; import com.trendrr.strest.server.v2.servers.ServerListenerBase; import com.trendrr.strest.server.v2.servers.StrestHttpServerListener; import com.trendrr.strest.server.v2.servers.StrestJsonServerListener; /** * @author Dustin Norlander * @created Feb 15, 2011 * */ public class StrestServer { protected static Log log = LogFactory.getLog(StrestServer.class); private StrestRouter router = new StrestRouter(); private Integer port = 8008; private Integer sslPort = 8009; private Executor bossExecutor = Executors.newCachedThreadPool(); private Executor workerExecutor = new MemoryAwareThreadPoolExecutor( 16, 1048576, 1048576); protected HashMap<String, ServerListenerBase> listeners = new HashMap<String, ServerListenerBase>(); protected HashMap<String, Class<? extends ServerListenerBase>> listenerClasses = new HashMap<String, Class<? extends ServerListenerBase>>(); private SSLContext sslContext = null; private DynMap config = new DynMap(); //private local config. public StrestServer() { //hard coded listener classes.. this.listenerClasses.put("http", StrestHttpServerListener.class); this.listenerClasses.put("json", StrestJsonServerListener.class); } public void registerListenerClass(String name, Class cls) { this.listenerClasses.put(name, cls); } /** * initializes the passed in server. Use this if you need to override the * StrestServer or set a new Router, ect. * * In other cases you should use the the StrestServer.instance methods * * @param server * @param config * @throws Exception */ public void initialize(DynMap config) throws Exception { if (config == null) { throw new Exception("Config is null! unable to initialize server "); } // this.setMaxWorkerThreads(config.getInteger("threads.worker", 10)); // this.setMaxIOThreads(config.getInteger("threads.io",8)); List<String> controllerPackages = config.getList(String.class, "controller_packages"); if (controllerPackages != null) { for (String c : controllerPackages) { this.getRouter().addControllerPackage(c); } } List<String> filters = config.getList(String.class, "filters"); if (filters != null) { this.getRouter().setFilters("default", filters); } this.getRouter().setServer(this); //now initialize the listeners. DynMap listeners = config.getMap("listeners", new DynMap()); for (String name : listeners.keySet()) { DynMap listenerConfig = listeners.getMap(name, new DynMap()); ServerListenerBase listener = null; if (listenerConfig.getString("classname") != null) { listener = Reflection.instance(ServerListenerBase.class, listenerConfig.getString("classname"), this, listenerConfig); } else { Class<? extends ServerListenerBase> cls = this.listenerClasses.get(name); if (cls == null) { log.warn("No listener class found for " + name + ", skipping"); continue; } log.warn("creating: " + cls); listener = Reflection.instance(cls, this, listenerConfig); } if (listener == null) { log.warn("No listener class found for " + name + ", skipping"); continue; } this.listeners.put(name, listener); } this.config = config; } public StrestRouter getRouter() { return router; } public Integer getPort() { return port; } public void setPort(Integer defaultPort) { this.port = defaultPort; } public Integer getSslPort() { return sslPort; } public void setSslPort(Integer sslPort) { this.sslPort = sslPort; } public void setRouter(StrestRouter router) { this.router = router; this.router.setServer(this); } public SSLContext getSSLContext() { return sslContext; } /** * sets the ssl context. If you would like this server to run in SSL mode * provide this. * * Recommended to create via the SSLContextBuilder provided. * * @param sslContext */ public void setSSLContext(SSLContext sslContext) { this.sslContext = sslContext; } public Executor getWorkerExecutor() { return workerExecutor; } public void setWorkerExecutor(Executor workerExecutor) { this.workerExecutor = workerExecutor; } // /** // * will set the workerExecutor to a fixed pool with maxThreads number of threads. // * // * -1 or null will set to unlimited. // * // * @param maxThreads // */ // public void setMaxWorkerThreads(Integer maxThreads) { // if (maxThreads == null || maxThreads < 1) { // this.workerExecutor = Executors.newCachedThreadPool(); // } else { // log.info("Setting max worker threads: " + maxThreads); // this.workerExecutor = Executors.newFixedThreadPool(maxThreads); // } // } // // /** // * will set the bossExecutor to a fixed pool with maxThreads number of threads. // * // * -1 or null will set to unlimited. // * // * @param maxThreads // */ // public void setMaxIOThreads(Integer maxThreads) { // if (maxThreads == null || maxThreads < 1) { // this.bossExecutor = Executors.newCachedThreadPool(); // } else { // log.info("Setting max IO threads: " + maxThreads); // this.bossExecutor = Executors.newFixedThreadPool(maxThreads); // } // } /** * starts all the listeners. */ public void start() { if (this.listeners.isEmpty()) { log.warn("No listeners configured. Goodbye"); System.exit(1); } for (ServerListenerBase listener : this.listeners.values()) { listener.start(bossExecutor, workerExecutor); } } /** * The original config file. Is typically parsed from a yaml file. * @return */ public DynMap getConfig() { return config; } public void shutdown() { for (ServerListenerBase listener : this.listeners.values()) { listener.stop(); } } }