SimpleHttpServerJaxWsServiceExporter.java 6.9 KB
Newer Older
A
Arjen Poutsma 已提交
1
/*
S
Stephane Nicoll 已提交
2
 * Copyright 2002-2014 the original author or authors.
A
Arjen Poutsma 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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 org.springframework.remoting.jaxws;

import java.net.InetSocketAddress;
import java.util.List;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
23
import javax.xml.ws.WebServiceProvider;
A
Arjen Poutsma 已提交
24 25 26 27 28 29 30

import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
S
Stephane Nicoll 已提交
31
import org.springframework.core.UsesSunHttpServer;
A
Arjen Poutsma 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

/**
 * Simple exporter for JAX-WS services, autodetecting annotated service beans
 * (through the JAX-WS {@link javax.jws.WebService} annotation) and exporting
 * them through the HTTP server included in Sun's JDK 1.6. The full address
 * for each service will consist of the server's base address with the
 * service name appended (e.g. "http://localhost:8080/OrderService").
 *
 * <p>Note that this exporter will only work on Sun's JDK 1.6 or higher, as well
 * as on JDKs that ship Sun's entire class library as included in the Sun JDK.
 * For a portable JAX-WS exporter, have a look at {@link SimpleJaxWsServiceExporter}.
 *
 * @author Juergen Hoeller
 * @since 2.5.5
 * @see javax.jws.WebService
 * @see javax.xml.ws.Endpoint#publish(Object)
 * @see SimpleJaxWsServiceExporter
 */
S
Stephane Nicoll 已提交
50
@UsesSunHttpServer
A
Arjen Poutsma 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
public class SimpleHttpServerJaxWsServiceExporter extends AbstractJaxWsServiceExporter {

	protected final Log logger = LogFactory.getLog(getClass());

	private HttpServer server;

	private int port = 8080;

	private String hostname;

	private int backlog = -1;

	private int shutdownDelay = 0;

	private String basePath = "/";

	private List<Filter> filters;

	private Authenticator authenticator;

	private boolean localServer = false;


	/**
	 * Specify an existing HTTP server to register the web service contexts
	 * with. This will typically be a server managed by the general Spring
	 * {@link org.springframework.remoting.support.SimpleHttpServerFactoryBean}.
	 * <p>Alternatively, configure a local HTTP server through the
	 * {@link #setPort "port"}, {@link #setHostname "hostname"} and
	 * {@link #setBacklog "backlog"} properties (or rely on the defaults there).
	 */
	public void setServer(HttpServer server) {
		this.server = server;
	}

	/**
	 * Specify the HTTP server's port. Default is 8080.
	 * <p>Only applicable for a locally configured HTTP server.
	 * Ignored when the {@link #setServer "server"} property has been specified.
	 */
	public void setPort(int port) {
		this.port = port;
	}

	/**
	 * Specify the HTTP server's hostname to bind to. Default is localhost;
	 * can be overridden with a specific network address to bind to.
	 * <p>Only applicable for a locally configured HTTP server.
	 * Ignored when the {@link #setServer "server"} property has been specified.
	 */
	public void setHostname(String hostname) {
		this.hostname = hostname;
	}

	/**
	 * Specify the HTTP server's TCP backlog. Default is -1,
	 * indicating the system's default value.
	 * <p>Only applicable for a locally configured HTTP server.
	 * Ignored when the {@link #setServer "server"} property has been specified.
	 */
	public void setBacklog(int backlog) {
		this.backlog = backlog;
	}

	/**
	 * Specify the number of seconds to wait until HTTP exchanges have
	 * completed when shutting down the HTTP server. Default is 0.
	 * <p>Only applicable for a locally configured HTTP server.
	 * Ignored when the {@link #setServer "server"} property has been specified.
	 */
	public void setShutdownDelay(int shutdownDelay) {
		this.shutdownDelay = shutdownDelay;
	}

	/**
	 * Set the base path for context publication. Default is "/".
	 * <p>For each context publication path, the service name will be
	 * appended to this base address. E.g. service name "OrderService"
	 * -> "/OrderService".
	 * @see javax.xml.ws.Endpoint#publish(Object)
	 * @see javax.jws.WebService#serviceName()
	 */
	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

	/**
	 * Register common {@link com.sun.net.httpserver.Filter Filters} to be
	 * applied to all detected {@link javax.jws.WebService} annotated beans.
	 */
	public void setFilters(List<Filter> filters) {
		this.filters = filters;
	}

	/**
	 * Register a common {@link com.sun.net.httpserver.Authenticator} to be
	 * applied to all detected {@link javax.jws.WebService} annotated beans.
	 */
	public void setAuthenticator(Authenticator authenticator) {
		this.authenticator = authenticator;
	}


154
	@Override
A
Arjen Poutsma 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167 168
	public void afterPropertiesSet() throws Exception {
		if (this.server == null) {
			InetSocketAddress address = (this.hostname != null ?
					new InetSocketAddress(this.hostname, this.port) : new InetSocketAddress(this.port));
			this.server = HttpServer.create(address, this.backlog);
			if (this.logger.isInfoEnabled()) {
				this.logger.info("Starting HttpServer at address " + address);
			}
			this.server.start();
			this.localServer = true;
		}
		super.afterPropertiesSet();
	}

169
	@Override
A
Arjen Poutsma 已提交
170
	protected void publishEndpoint(Endpoint endpoint, WebService annotation) {
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
		endpoint.publish(buildHttpContext(endpoint, annotation.serviceName()));
	}

	@Override
	protected void publishEndpoint(Endpoint endpoint, WebServiceProvider annotation) {
		endpoint.publish(buildHttpContext(endpoint, annotation.serviceName()));
	}

	/**
	 * Build the HttpContext for the given endpoint.
	 * @param endpoint the JAX-WS Provider Endpoint object
	 * @param serviceName the given service name
	 * @return the fully populated HttpContext
	 */
	protected HttpContext buildHttpContext(Endpoint endpoint, String serviceName) {
		String fullPath = calculateEndpointPath(endpoint, serviceName);
A
Arjen Poutsma 已提交
187 188 189 190 191 192 193
		HttpContext httpContext = this.server.createContext(fullPath);
		if (this.filters != null) {
			httpContext.getFilters().addAll(this.filters);
		}
		if (this.authenticator != null) {
			httpContext.setAuthenticator(this.authenticator);
		}
194 195 196 197 198 199 200 201 202 203 204
		return httpContext;
	}

	/**
	 * Calculate the full endpoint path for the given endpoint.
	 * @param endpoint the JAX-WS Provider Endpoint object
	 * @param serviceName the given service name
	 * @return the full endpoint path
	 */
	protected String calculateEndpointPath(Endpoint endpoint, String serviceName) {
		return this.basePath + serviceName;
A
Arjen Poutsma 已提交
205 206
	}

207

208
	@Override
A
Arjen Poutsma 已提交
209 210 211 212 213 214 215 216 217
	public void destroy() {
		super.destroy();
		if (this.localServer) {
			logger.info("Stopping HttpServer");
			this.server.stop(this.shutdownDelay);
		}
	}

}