/jboss-as-7.1.1.Final/web/src/main/java/org/jboss/as/web/WebConnectorService.java
Java | 417 lines | 321 code | 45 blank | 51 comment | 65 complexity | 4501a307f690f345cd6d7ba4eaeff85f MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
1/*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2010, Red Hat Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22package org.jboss.as.web;
23
24import static org.jboss.as.web.WebMessages.MESSAGES;
25
26import java.io.IOException;
27import java.lang.reflect.Method;
28import java.net.InetAddress;
29import java.net.InetSocketAddress;
30import java.util.HashSet;
31import java.util.concurrent.Executor;
32
33import org.apache.catalina.connector.Connector;
34import org.apache.coyote.ajp.AjpAprProtocol;
35import org.apache.coyote.ajp.AjpProtocol;
36import org.apache.coyote.http11.Http11AprProtocol;
37import org.jboss.as.network.ManagedBinding;
38import org.jboss.as.network.SocketBinding;
39import org.jboss.dmr.ModelNode;
40import org.jboss.msc.service.Service;
41import org.jboss.msc.service.StartContext;
42import org.jboss.msc.service.StartException;
43import org.jboss.msc.service.StopContext;
44import org.jboss.msc.value.InjectedValue;
45
46/**
47 * Service creating and starting a web connector.
48 *
49 * @author Emanuel Muckenhuber
50 */
51class WebConnectorService implements Service<Connector> {
52
53 private volatile String protocol = "HTTP/1.1";
54 private volatile String scheme = "http";
55
56 private Boolean enableLookups = null;
57 private String proxyName = null;
58 private Integer proxyPort = null;
59 private Integer redirectPort = null;
60 private Boolean secure = null;
61 private Integer maxPostSize = null;
62 private Integer maxSavePostSize = null;
63 private Integer maxConnections = null;
64 private ModelNode ssl;
65 private ModelNode virtualServers;
66
67 private Connector connector;
68
69 private final InjectedValue<Executor> executor = new InjectedValue<Executor>();
70 private final InjectedValue<SocketBinding> binding = new InjectedValue<SocketBinding>();
71 private final InjectedValue<WebServer> server = new InjectedValue<WebServer>();
72
73 public WebConnectorService(String protocol, String scheme) {
74 if(protocol != null) this.protocol = protocol;
75 if(scheme != null) this.scheme = scheme;
76 }
77
78 /**
79 * Start, register and bind the web connector.
80 *
81 * @param context the start context
82 * @throws StartException if the connector cannot be started
83 */
84 public synchronized void start(StartContext context) throws StartException {
85 final SocketBinding binding = this.binding.getValue();
86 final InetSocketAddress address = binding.getSocketAddress();
87 final Executor executor = this.executor.getOptionalValue();
88 try {
89 // Create connector
90 final Connector connector = new Connector(protocol);
91 connector.setPort(address.getPort());
92 connector.setScheme(scheme);
93 if(enableLookups != null) connector.setEnableLookups(enableLookups);
94 if(maxPostSize != null) connector.setMaxPostSize(maxPostSize);
95 if(maxSavePostSize != null) connector.setMaxSavePostSize(maxSavePostSize);
96 if(proxyName != null) connector.setProxyName(proxyName);
97 if(proxyPort != null) connector.setProxyPort(proxyPort);
98 if(redirectPort != null) connector.setRedirectPort(redirectPort);
99 if(secure != null) connector.setSecure(secure);
100 boolean nativeProtocolHandler = false;
101 if (connector.getProtocolHandler() instanceof Http11AprProtocol
102 || connector.getProtocolHandler() instanceof AjpAprProtocol) {
103 nativeProtocolHandler = true;
104 }
105 if (executor != null) {
106 Method m = connector.getProtocolHandler().getClass().getMethod("setExecutor", Executor.class);
107 m.invoke(connector.getProtocolHandler(), executor);
108 }
109 if (address != null && address.getAddress() != null) {
110 Method m = connector.getProtocolHandler().getClass().getMethod("setAddress", InetAddress.class);
111 m.invoke(connector.getProtocolHandler(), address.getAddress());
112 }
113 if (maxConnections != null) {
114 try {
115 Method m = connector.getProtocolHandler().getClass().getMethod("setPollerSize", Integer.TYPE);
116 m.invoke(connector.getProtocolHandler(), maxConnections);
117 } catch (NoSuchMethodException e) {
118 // Not all connectors will have this
119 }
120 if (nativeProtocolHandler) {
121 try {
122 Method m = connector.getProtocolHandler().getClass().getMethod("setSendfileSize", Integer.TYPE);
123 m.invoke(connector.getProtocolHandler(), maxConnections);
124 } catch (NoSuchMethodException e) {
125 // Not all connectors will have this
126 }
127 } else {
128 Method m = connector.getProtocolHandler().getClass().getMethod("setMaxThreads", Integer.TYPE);
129 m.invoke(connector.getProtocolHandler(), maxConnections);
130 }
131 }
132 if (virtualServers != null) {
133 HashSet<String> virtualServersList = new HashSet<String>();
134 for (final ModelNode virtualServer : virtualServers.asList()) {
135 virtualServersList.add(virtualServer.asString());
136 }
137 connector.setAllowedHosts(virtualServersList);
138 }
139 if (ssl != null) {
140 boolean nativeSSL = false;
141 if (connector.getProtocolHandler() instanceof Http11AprProtocol) {
142 nativeSSL = true;
143 } else if ((connector.getProtocolHandler() instanceof AjpProtocol) || (connector.getProtocolHandler() instanceof AjpAprProtocol)) {
144 throw new StartException(MESSAGES.noSSLWithNonHTTPConnectors());
145 }
146 // Enable SSL
147 try {
148 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLEnabled", Boolean.TYPE);
149 m.invoke(connector.getProtocolHandler(), true);
150 } catch (NoSuchMethodException e) {
151 // No SSL support
152 throw new StartException(MESSAGES.failedSSLConfiguration(), e);
153 }
154 if (nativeSSL) {
155 // OpenSSL configuration
156 try {
157 if (ssl.hasDefined(Constants.PASSWORD)) {
158 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLPassword", String.class);
159 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.PASSWORD).asString());
160 }
161 if (ssl.hasDefined(Constants.CERTIFICATE_KEY_FILE)) {
162 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLCertificateKeyFile", String.class);
163 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CERTIFICATE_KEY_FILE).asString());
164 }
165 if (ssl.hasDefined(Constants.CIPHER_SUITE)) {
166 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLCipherSuite", String.class);
167 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CIPHER_SUITE).asString());
168 }
169 if (ssl.hasDefined(Constants.PROTOCOL)) {
170 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLProtocol", String.class);
171 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.PROTOCOL).asString());
172 }
173 if (ssl.hasDefined(Constants.VERIFY_CLIENT)) {
174 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLVerifyClient", String.class);
175 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.VERIFY_CLIENT).asString());
176 }
177 if (ssl.hasDefined(Constants.VERIFY_DEPTH)) {
178 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLVerifyDepth", Integer.TYPE);
179 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.VERIFY_DEPTH).asInt());
180 }
181 if (ssl.hasDefined(Constants.CERTIFICATE_FILE)) {
182 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLCertificateFile", String.class);
183 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CERTIFICATE_FILE).asString());
184 }
185 if (ssl.hasDefined(Constants.CA_CERTIFICATE_FILE)) {
186 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLCACertificateFile", String.class);
187 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CA_CERTIFICATE_FILE).asString());
188 }
189 if (ssl.hasDefined(Constants.CA_REVOCATION_URL)) {
190 Method m = connector.getProtocolHandler().getClass().getMethod("setSSLCARevocationFile", String.class);
191 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CA_REVOCATION_URL).asString());
192 }
193 } catch (NoSuchMethodException e) {
194 throw new StartException(MESSAGES.failedSSLConfiguration(), e);
195 }
196 } else {
197 // JSSE configuration
198 try {
199 if (ssl.hasDefined(Constants.KEY_ALIAS)) {
200 Method m = connector.getProtocolHandler().getClass().getMethod("setKeyAlias", String.class);
201 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.KEY_ALIAS).asString());
202 }
203 if (ssl.hasDefined(Constants.PASSWORD)) {
204 Method m = connector.getProtocolHandler().getClass().getMethod("setKeypass", String.class);
205 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.PASSWORD).asString());
206 }
207 if (ssl.hasDefined(Constants.CERTIFICATE_KEY_FILE)) {
208 Method m = connector.getProtocolHandler().getClass().getMethod("setKeystore", String.class);
209 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CERTIFICATE_KEY_FILE).asString());
210 }
211 if (ssl.hasDefined(Constants.CIPHER_SUITE)) {
212 Method m = connector.getProtocolHandler().getClass().getMethod("setCiphers", String.class);
213 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.CIPHER_SUITE).asString());
214 }
215 if (ssl.hasDefined(Constants.PROTOCOL)) {
216 Method m = connector.getProtocolHandler().getClass().getMethod("setProtocols", String.class);
217 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.PROTOCOL).asString());
218 }
219 if (ssl.hasDefined(Constants.VERIFY_CLIENT)) {
220 Method m = connector.getProtocolHandler().getClass().getMethod("setClientauth", String.class);
221 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.VERIFY_CLIENT).asString());
222 }
223 if (ssl.hasDefined(Constants.SESSION_CACHE_SIZE)) {
224 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
225 m.invoke(connector.getProtocolHandler(), "sessionCacheSize", ssl.get(Constants.SESSION_CACHE_SIZE).asString());
226 }
227 if (ssl.hasDefined(Constants.SESSION_TIMEOUT)) {
228 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
229 m.invoke(connector.getProtocolHandler(), "sessionCacheTimeout", ssl.get(Constants.SESSION_TIMEOUT).asString());
230 }
231 /* possible attributes that apply to ssl socket factory
232 keystoreType -> PKCS12
233 keystore -> path/to/keystore.p12
234 keypass -> key password
235 truststorePass -> trustPassword
236 truststoreFile -> path/to/truststore.jks
237 truststoreType -> JKS
238 */
239 if (ssl.hasDefined(Constants.CA_CERTIFICATE_FILE)) {
240 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
241 m.invoke(connector.getProtocolHandler(), "truststoreFile", ssl.get(Constants.CA_CERTIFICATE_FILE).asString());
242
243 }
244 if (ssl.hasDefined(Constants.CA_CERTIFICATE_PASSWORD)) {
245 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
246 m.invoke(connector.getProtocolHandler(), "truststorePass",ssl.get(Constants.CA_CERTIFICATE_PASSWORD).asString());
247 }
248 if (ssl.hasDefined(Constants.TRUSTSTORE_TYPE)) {
249 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
250 m.invoke(connector.getProtocolHandler(), "truststoreType",ssl.get(Constants.TRUSTSTORE_TYPE).asString());
251 }
252 if (ssl.hasDefined(Constants.KEYSTORE_TYPE)) {
253 Method m = connector.getProtocolHandler().getClass().getMethod("setKeytype", String.class);
254 m.invoke(connector.getProtocolHandler(), ssl.get(Constants.KEYSTORE_TYPE).asString());
255 }
256 if (ssl.hasDefined(Constants.CA_REVOCATION_URL)) {
257 Method m = connector.getProtocolHandler().getClass().getMethod("setAttribute", String.class, Object.class);
258 m.invoke(connector.getProtocolHandler(), "crlFile", ssl.get(Constants.CA_REVOCATION_URL).asString());
259 }
260
261 } catch (NoSuchMethodException e) {
262 throw new StartException(MESSAGES.failedSSLConfiguration(), e);
263 }
264 }
265 }
266 getWebServer().addConnector(connector);
267 connector.init();
268 connector.start();
269 this.connector = connector;
270 } catch (Exception e) {
271 throw new StartException(MESSAGES.connectorStartError(), e);
272 }
273 // Register the binding after the connector is started
274 binding.getSocketBindings().getNamedRegistry().registerBinding(new ConnectorBinding(binding));
275 }
276
277
278
279 /** {@inheritDoc} */
280 public synchronized void stop(StopContext context) {
281 final SocketBinding binding = this.binding.getValue();
282 binding.getSocketBindings().getNamedRegistry().unregisterBinding(binding.getName());
283 final Connector connector = this.connector;
284 try {
285 connector.pause();
286 } catch (Exception e) {
287 }
288 try {
289 connector.stop();
290 } catch (Exception e) {
291 }
292 getWebServer().removeConnector(connector);
293 this.connector = null;
294 }
295
296 /** {@inheritDoc} */
297 public synchronized Connector getValue() throws IllegalStateException {
298 final Connector connector = this.connector;
299 if (connector == null) {
300 throw MESSAGES.nullValue();
301 }
302 return connector;
303 }
304
305 void setSsl(final ModelNode ssl) {
306 this.ssl = ssl;
307 }
308
309 void setVirtualServers(ModelNode virtualServers) {
310 this.virtualServers = virtualServers;
311 }
312
313 protected boolean isEnableLookups() {
314 return enableLookups;
315 }
316
317 protected void setEnableLookups(boolean enableLookups) {
318 this.enableLookups = enableLookups;
319 }
320
321 protected String getProxyName() {
322 return proxyName;
323 }
324
325 protected void setProxyName(String proxyName) {
326 this.proxyName = proxyName;
327 }
328
329 protected int getProxyPort() {
330 return proxyPort;
331 }
332
333 protected void setProxyPort(int proxyPort) {
334 this.proxyPort = proxyPort;
335 }
336
337 protected int getRedirectPort() {
338 return redirectPort;
339 }
340
341 protected void setRedirectPort(int redirectPort) {
342 this.redirectPort = redirectPort;
343 }
344
345 protected boolean isSecure() {
346 return secure;
347 }
348
349 protected void setSecure(boolean secure) {
350 this.secure = secure;
351 }
352
353 protected int getMaxPostSize() {
354 return maxPostSize;
355 }
356
357 protected void setMaxPostSize(int maxPostSize) {
358 this.maxPostSize = maxPostSize;
359 }
360
361 protected int getMaxSavePostSize() {
362 return maxSavePostSize;
363 }
364
365 protected void setMaxSavePostSize(int maxSavePostSize) {
366 this.maxSavePostSize = maxSavePostSize;
367 }
368
369 protected int getMaxConnections() {
370 return maxConnections;
371 }
372
373 protected void setMaxConnections(int maxConnections) {
374 this.maxConnections = maxConnections;
375 }
376
377 InjectedValue<Executor> getExecutor() {
378 return executor;
379 }
380
381 InjectedValue<SocketBinding> getBinding() {
382 return binding;
383 }
384
385 InjectedValue<WebServer> getServer() {
386 return server;
387 }
388
389 private WebServer getWebServer() {
390 return server.getValue();
391 }
392
393 static class ConnectorBinding implements ManagedBinding {
394
395 private final SocketBinding binding;
396
397 private ConnectorBinding(final SocketBinding binding) {
398 this.binding = binding;
399 }
400
401 @Override
402 public String getSocketBindingName() {
403 return binding.getName();
404 }
405
406 @Override
407 public InetSocketAddress getBindAddress() {
408 return binding.getSocketAddress();
409 }
410
411 @Override
412 public void close() throws IOException {
413 // TODO should this do something?
414 }
415 }
416
417}