001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.remoting.support; 018 019import java.io.IOException; 020import java.net.InetSocketAddress; 021import java.util.List; 022import java.util.Map; 023import java.util.concurrent.Executor; 024 025import com.sun.net.httpserver.Authenticator; 026import com.sun.net.httpserver.Filter; 027import com.sun.net.httpserver.HttpContext; 028import com.sun.net.httpserver.HttpHandler; 029import com.sun.net.httpserver.HttpServer; 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032 033import org.springframework.beans.factory.DisposableBean; 034import org.springframework.beans.factory.FactoryBean; 035import org.springframework.beans.factory.InitializingBean; 036import org.springframework.lang.UsesSunHttpServer; 037 038/** 039 * {@link org.springframework.beans.factory.FactoryBean} that creates a simple 040 * HTTP server, based on the HTTP server that is included in Sun's JRE 1.6. 041 * Starts the HTTP server on initialization and stops it on destruction. 042 * Exposes the resulting {@link com.sun.net.httpserver.HttpServer} object. 043 * 044 * <p>Allows for registering {@link com.sun.net.httpserver.HttpHandler HttpHandlers} 045 * for specific {@link #setContexts context paths}. Alternatively, 046 * register such context-specific handlers programmatically on the 047 * {@link com.sun.net.httpserver.HttpServer} itself. 048 * 049 * @author Juergen Hoeller 050 * @author Arjen Poutsma 051 * @since 2.5.1 052 * @see #setPort 053 * @see #setContexts 054 */ 055@UsesSunHttpServer 056public class SimpleHttpServerFactoryBean implements FactoryBean<HttpServer>, InitializingBean, DisposableBean { 057 058 protected final Log logger = LogFactory.getLog(getClass()); 059 060 private int port = 8080; 061 062 private String hostname; 063 064 private int backlog = -1; 065 066 private int shutdownDelay = 0; 067 068 private Executor executor; 069 070 private Map<String, HttpHandler> contexts; 071 072 private List<Filter> filters; 073 074 private Authenticator authenticator; 075 076 private HttpServer server; 077 078 079 /** 080 * Specify the HTTP server's port. Default is 8080. 081 */ 082 public void setPort(int port) { 083 this.port = port; 084 } 085 086 /** 087 * Specify the HTTP server's hostname to bind to. Default is localhost; 088 * can be overridden with a specific network address to bind to. 089 */ 090 public void setHostname(String hostname) { 091 this.hostname = hostname; 092 } 093 094 /** 095 * Specify the HTTP server's TCP backlog. Default is -1, 096 * indicating the system's default value. 097 */ 098 public void setBacklog(int backlog) { 099 this.backlog = backlog; 100 } 101 102 /** 103 * Specify the number of seconds to wait until HTTP exchanges have 104 * completed when shutting down the HTTP server. Default is 0. 105 */ 106 public void setShutdownDelay(int shutdownDelay) { 107 this.shutdownDelay = shutdownDelay; 108 } 109 110 /** 111 * Set the JDK concurrent executor to use for dispatching incoming requests. 112 * @see com.sun.net.httpserver.HttpServer#setExecutor 113 */ 114 public void setExecutor(Executor executor) { 115 this.executor = executor; 116 } 117 118 /** 119 * Register {@link com.sun.net.httpserver.HttpHandler HttpHandlers} 120 * for specific context paths. 121 * @param contexts a Map with context paths as keys and HttpHandler 122 * objects as values 123 * @see org.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExporter 124 * @see org.springframework.remoting.caucho.SimpleHessianServiceExporter 125 * @see org.springframework.remoting.caucho.SimpleBurlapServiceExporter 126 */ 127 public void setContexts(Map<String, HttpHandler> contexts) { 128 this.contexts = contexts; 129 } 130 131 /** 132 * Register common {@link com.sun.net.httpserver.Filter Filters} to be 133 * applied to all locally registered {@link #setContexts contexts}. 134 */ 135 public void setFilters(List<Filter> filters) { 136 this.filters = filters; 137 } 138 139 /** 140 * Register a common {@link com.sun.net.httpserver.Authenticator} to be 141 * applied to all locally registered {@link #setContexts contexts}. 142 */ 143 public void setAuthenticator(Authenticator authenticator) { 144 this.authenticator = authenticator; 145 } 146 147 148 @Override 149 public void afterPropertiesSet() throws IOException { 150 InetSocketAddress address = (this.hostname != null ? 151 new InetSocketAddress(this.hostname, this.port) : new InetSocketAddress(this.port)); 152 this.server = HttpServer.create(address, this.backlog); 153 if (this.executor != null) { 154 this.server.setExecutor(this.executor); 155 } 156 if (this.contexts != null) { 157 for (String key : this.contexts.keySet()) { 158 HttpContext httpContext = this.server.createContext(key, this.contexts.get(key)); 159 if (this.filters != null) { 160 httpContext.getFilters().addAll(this.filters); 161 } 162 if (this.authenticator != null) { 163 httpContext.setAuthenticator(this.authenticator); 164 } 165 } 166 } 167 if (this.logger.isInfoEnabled()) { 168 this.logger.info("Starting HttpServer at address " + address); 169 } 170 this.server.start(); 171 } 172 173 @Override 174 public HttpServer getObject() { 175 return this.server; 176 } 177 178 @Override 179 public Class<? extends HttpServer> getObjectType() { 180 return (this.server != null ? this.server.getClass() : HttpServer.class); 181 } 182 183 @Override 184 public boolean isSingleton() { 185 return true; 186 } 187 188 @Override 189 public void destroy() { 190 logger.info("Stopping HttpServer"); 191 this.server.stop(this.shutdownDelay); 192 } 193 194}