PageRenderTime 107ms CodeModel.GetById 17ms app.highlight 71ms RepoModel.GetById 0ms app.codeStats 1ms

/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}