001/*
002 * Copyright 2002-2018 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.jaxws;
018
019import java.net.InetSocketAddress;
020import java.util.List;
021
022import javax.jws.WebService;
023import javax.xml.ws.Endpoint;
024import javax.xml.ws.WebServiceProvider;
025
026import com.sun.net.httpserver.Authenticator;
027import com.sun.net.httpserver.Filter;
028import com.sun.net.httpserver.HttpContext;
029import com.sun.net.httpserver.HttpServer;
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032
033import org.springframework.lang.Nullable;
034import org.springframework.util.Assert;
035
036/**
037 * Simple exporter for JAX-WS services, autodetecting annotated service beans
038 * (through the JAX-WS {@link javax.jws.WebService} annotation) and exporting
039 * them through the HTTP server included in Sun's JDK 1.6. The full address
040 * for each service will consist of the server's base address with the
041 * service name appended (e.g. "http://localhost:8080/OrderService").
042 *
043 * <p>Note that this exporter will only work on Sun's JDK 1.6 or higher, as well
044 * as on JDKs that ship Sun's entire class library as included in the Sun JDK.
045 * For a portable JAX-WS exporter, have a look at {@link SimpleJaxWsServiceExporter}.
046 *
047 * @author Juergen Hoeller
048 * @since 2.5.5
049 * @see javax.jws.WebService
050 * @see javax.xml.ws.Endpoint#publish(Object)
051 * @see SimpleJaxWsServiceExporter
052 * @deprecated as of Spring Framework 5.1, in favor of {@link SimpleJaxWsServiceExporter}
053 */
054@Deprecated
055@org.springframework.lang.UsesSunHttpServer
056public class SimpleHttpServerJaxWsServiceExporter extends AbstractJaxWsServiceExporter {
057
058        protected final Log logger = LogFactory.getLog(getClass());
059
060        @Nullable
061        private HttpServer server;
062
063        private int port = 8080;
064
065        @Nullable
066        private String hostname;
067
068        private int backlog = -1;
069
070        private int shutdownDelay = 0;
071
072        private String basePath = "/";
073
074        @Nullable
075        private List<Filter> filters;
076
077        @Nullable
078        private Authenticator authenticator;
079
080        private boolean localServer = false;
081
082
083        /**
084         * Specify an existing HTTP server to register the web service contexts
085         * with. This will typically be a server managed by the general Spring
086         * {@link org.springframework.remoting.support.SimpleHttpServerFactoryBean}.
087         * <p>Alternatively, configure a local HTTP server through the
088         * {@link #setPort "port"}, {@link #setHostname "hostname"} and
089         * {@link #setBacklog "backlog"} properties (or rely on the defaults there).
090         */
091        public void setServer(HttpServer server) {
092                this.server = server;
093        }
094
095        /**
096         * Specify the HTTP server's port. Default is 8080.
097         * <p>Only applicable for a locally configured HTTP server.
098         * Ignored when the {@link #setServer "server"} property has been specified.
099         */
100        public void setPort(int port) {
101                this.port = port;
102        }
103
104        /**
105         * Specify the HTTP server's hostname to bind to. Default is localhost;
106         * can be overridden with a specific network address to bind to.
107         * <p>Only applicable for a locally configured HTTP server.
108         * Ignored when the {@link #setServer "server"} property has been specified.
109         */
110        public void setHostname(String hostname) {
111                this.hostname = hostname;
112        }
113
114        /**
115         * Specify the HTTP server's TCP backlog. Default is -1,
116         * indicating the system's default value.
117         * <p>Only applicable for a locally configured HTTP server.
118         * Ignored when the {@link #setServer "server"} property has been specified.
119         */
120        public void setBacklog(int backlog) {
121                this.backlog = backlog;
122        }
123
124        /**
125         * Specify the number of seconds to wait until HTTP exchanges have
126         * completed when shutting down the HTTP server. Default is 0.
127         * <p>Only applicable for a locally configured HTTP server.
128         * Ignored when the {@link #setServer "server"} property has been specified.
129         */
130        public void setShutdownDelay(int shutdownDelay) {
131                this.shutdownDelay = shutdownDelay;
132        }
133
134        /**
135         * Set the base path for context publication. Default is "/".
136         * <p>For each context publication path, the service name will be
137         * appended to this base address. E.g. service name "OrderService"
138         * -> "/OrderService".
139         * @see javax.xml.ws.Endpoint#publish(Object)
140         * @see javax.jws.WebService#serviceName()
141         */
142        public void setBasePath(String basePath) {
143                this.basePath = basePath;
144        }
145
146        /**
147         * Register common {@link com.sun.net.httpserver.Filter Filters} to be
148         * applied to all detected {@link javax.jws.WebService} annotated beans.
149         */
150        public void setFilters(List<Filter> filters) {
151                this.filters = filters;
152        }
153
154        /**
155         * Register a common {@link com.sun.net.httpserver.Authenticator} to be
156         * applied to all detected {@link javax.jws.WebService} annotated beans.
157         */
158        public void setAuthenticator(Authenticator authenticator) {
159                this.authenticator = authenticator;
160        }
161
162
163        @Override
164        public void afterPropertiesSet() throws Exception {
165                if (this.server == null) {
166                        InetSocketAddress address = (this.hostname != null ?
167                                        new InetSocketAddress(this.hostname, this.port) : new InetSocketAddress(this.port));
168                        HttpServer server = HttpServer.create(address, this.backlog);
169                        if (logger.isInfoEnabled()) {
170                                logger.info("Starting HttpServer at address " + address);
171                        }
172                        server.start();
173                        this.server = server;
174                        this.localServer = true;
175                }
176                super.afterPropertiesSet();
177        }
178
179        @Override
180        protected void publishEndpoint(Endpoint endpoint, WebService annotation) {
181                endpoint.publish(buildHttpContext(endpoint, annotation.serviceName()));
182        }
183
184        @Override
185        protected void publishEndpoint(Endpoint endpoint, WebServiceProvider annotation) {
186                endpoint.publish(buildHttpContext(endpoint, annotation.serviceName()));
187        }
188
189        /**
190         * Build the HttpContext for the given endpoint.
191         * @param endpoint the JAX-WS Provider Endpoint object
192         * @param serviceName the given service name
193         * @return the fully populated HttpContext
194         */
195        protected HttpContext buildHttpContext(Endpoint endpoint, String serviceName) {
196                Assert.state(this.server != null, "No HttpServer available");
197                String fullPath = calculateEndpointPath(endpoint, serviceName);
198                HttpContext httpContext = this.server.createContext(fullPath);
199                if (this.filters != null) {
200                        httpContext.getFilters().addAll(this.filters);
201                }
202                if (this.authenticator != null) {
203                        httpContext.setAuthenticator(this.authenticator);
204                }
205                return httpContext;
206        }
207
208        /**
209         * Calculate the full endpoint path for the given endpoint.
210         * @param endpoint the JAX-WS Provider Endpoint object
211         * @param serviceName the given service name
212         * @return the full endpoint path
213         */
214        protected String calculateEndpointPath(Endpoint endpoint, String serviceName) {
215                return this.basePath + serviceName;
216        }
217
218
219        @Override
220        public void destroy() {
221                super.destroy();
222                if (this.server != null && this.localServer) {
223                        logger.info("Stopping HttpServer");
224                        this.server.stop(this.shutdownDelay);
225                }
226        }
227
228}