1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.catalina.connector;
18
19 import java.io.UnsupportedEncodingException;
20 import java.net.InetAddress;
21 import java.nio.charset.Charset;
22 import java.nio.charset.StandardCharsets;
23 import java.util.Arrays;
24 import java.util.HashSet;
25
26 import javax.management.ObjectName;
27
28 import org.apache.catalina.Globals;
29 import org.apache.catalina.LifecycleException;
30 import org.apache.catalina.LifecycleState;
31 import org.apache.catalina.Service;
32 import org.apache.catalina.core.AprLifecycleListener;
33 import org.apache.catalina.util.LifecycleMBeanBase;
34 import org.apache.coyote.AbstractProtocol;
35 import org.apache.coyote.Adapter;
36 import org.apache.coyote.ProtocolHandler;
37 import org.apache.coyote.UpgradeProtocol;
38 import org.apache.coyote.ajp.AbstractAjpProtocol;
39 import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
40 import org.apache.juli.logging.Log;
41 import org.apache.juli.logging.LogFactory;
42 import org.apache.tomcat.util.IntrospectionUtils;
43 import org.apache.tomcat.util.buf.B2CConverter;
44 import org.apache.tomcat.util.net.SSLHostConfig;
45 import org.apache.tomcat.util.net.openssl.OpenSSLImplementation;
46 import org.apache.tomcat.util.res.StringManager;
47
48
49 /**
50  * Implementation of a Coyote connector.
51  *
52  * @author Craig R. McClanahan
53  * @author Remy Maucherat
54  */

55 public class Connector extends LifecycleMBeanBase  {
56
57     private static final Log log = LogFactory.getLog(Connector.class);
58
59
60     /**
61      * Alternate flag to enable recycling of facades.
62      */

63     public static final boolean RECYCLE_FACADES =
64         Boolean.parseBoolean(System.getProperty("org.apache.catalina.connector.RECYCLE_FACADES""false"));
65
66
67     public static final String INTERNAL_EXECUTOR_NAME = "Internal";
68
69
70     // ------------------------------------------------------------ Constructor
71
72     /**
73      * Defaults to using HTTP/1.1 NIO implementation.
74      */

75     public Connector() {
76         this("org.apache.coyote.http11.Http11NioProtocol");
77     }
78
79
80     public Connector(String protocol) {
81         boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
82                 AprLifecycleListener.getUseAprConnector();
83
84         if ("HTTP/1.1".equals(protocol) || protocol == null) {
85             if (aprConnector) {
86                 protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";
87             } else {
88                 protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";
89             }
90         } else if ("AJP/1.3".equals(protocol)) {
91             if (aprConnector) {
92                 protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";
93             } else {
94                 protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";
95             }
96         } else {
97             protocolHandlerClassName = protocol;
98         }
99
100         // Instantiate protocol handler
101         ProtocolHandler p = null;
102         try {
103             Class<?> clazz = Class.forName(protocolHandlerClassName);
104             p = (ProtocolHandler) clazz.getConstructor().newInstance();
105         } catch (Exception e) {
106             log.error(sm.getString(
107                     "coyoteConnector.protocolHandlerInstantiationFailed"), e);
108         } finally {
109             this.protocolHandler = p;
110         }
111
112         // Default for Connector depends on this system property
113         setThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
114     }
115
116
117     // ----------------------------------------------------- Instance Variables
118
119
120     /**
121      * The <code>Service</code> we are associated with (if any).
122      */

123     protected Service service = null;
124
125
126     /**
127      * Do we allow TRACE ?
128      */

129     protected boolean allowTrace = false;
130
131
132     /**
133      * Default timeout for asynchronous requests (ms).
134      */

135     protected long asyncTimeout = 30000;
136
137
138     /**
139      * The "enable DNS lookups" flag for this Connector.
140      */

141     protected boolean enableLookups = false;
142
143
144     /*
145      * Is generation of X-Powered-By response header enabled/disabled?
146      */

147     protected boolean xpoweredBy = false;
148
149
150     /**
151      * The server name to which we should pretend requests to this Connector
152      * were directed.  This is useful when operating Tomcat behind a proxy
153      * server, so that redirects get constructed accurately.  If not specified,
154      * the server name included in the <code>Host</code> header is used.
155      */

156     protected String proxyName = null;
157
158
159     /**
160      * The server port to which we should pretend requests to this Connector
161      * were directed.  This is useful when operating Tomcat behind a proxy
162      * server, so that redirects get constructed accurately.  If not specified,
163      * the port number specified by the <code>port</code> property is used.
164      */

165     protected int proxyPort = 0;
166
167
168     /**
169      * The flag that controls recycling of the facades of the request
170      * processing objects. If set to <code>true</code> the object facades
171      * will be discarded when the request is recycled. If the security
172      * manager is enabled, this setting is ignored and object facades are
173      * always discarded.
174      */

175     protected boolean discardFacades = RECYCLE_FACADES;
176
177
178     /**
179      * The redirect port for non-SSL to SSL redirects.
180      */

181     protected int redirectPort = 443;
182
183
184     /**
185      * The request scheme that will be set on all requests received
186      * through this connector.
187      */

188     protected String scheme = "http";
189
190
191     /**
192      * The secure connection flag that will be set on all requests received
193      * through this connector.
194      */

195     protected boolean secure = false;
196
197
198     /**
199      * The string manager for this package.
200      */

201     protected static final StringManager sm = StringManager.getManager(Connector.class);
202
203
204     /**
205      * The maximum number of cookies permitted for a request. Use a value less
206      * than zero for no limit. Defaults to 200.
207      */

208     private int maxCookieCount = 200;
209
210     /**
211      * The maximum number of parameters (GET plus POST) which will be
212      * automatically parsed by the container. 10000 by default. A value of less
213      * than 0 means no limit.
214      */

215     protected int maxParameterCount = 10000;
216
217     /**
218      * Maximum size of a POST which will be automatically parsed by the
219      * container. 2MB by default.
220      */

221     protected int maxPostSize = 2 * 1024 * 1024;
222
223
224     /**
225      * Maximum size of a POST which will be saved by the container
226      * during authentication. 4kB by default
227      */

228     protected int maxSavePostSize = 4 * 1024;
229
230     /**
231      * Comma-separated list of HTTP methods that will be parsed according
232      * to POST-style rules for application/x-www-form-urlencoded request bodies.
233      */

234     protected String parseBodyMethods = "POST";
235
236     /**
237      * A Set of methods determined by {@link #parseBodyMethods}.
238      */

239     protected HashSet<String> parseBodyMethodsSet;
240
241
242     /**
243      * Flag to use IP-based virtual hosting.
244      */

245     protected boolean useIPVHosts = false;
246
247
248     /**
249      * Coyote Protocol handler class name.
250      * See {@link #Connector()} for current default.
251      */

252     protected final String protocolHandlerClassName;
253
254
255     /**
256      * Coyote protocol handler.
257      */

258     protected final ProtocolHandler protocolHandler;
259
260
261     /**
262      * Coyote adapter.
263      */

264     protected Adapter adapter = null;
265
266
267     private Charset uriCharset = StandardCharsets.UTF_8;
268
269
270     /**
271      * URI encoding as body.
272      */

273     protected boolean useBodyEncodingForURI = false;
274
275
276     // ------------------------------------------------------------- Properties
277
278     /**
279      * Return a property from the protocol handler.
280      *
281      * @param name the property name
282      * @return the property value
283      */

284     public Object getProperty(String name) {
285         if (protocolHandler == null) {
286             return null;
287         }
288         return IntrospectionUtils.getProperty(protocolHandler, name);
289     }
290
291
292     /**
293      * Set a property on the protocol handler.
294      *
295      * @param name the property name
296      * @param value the property value
297      * @return <code>true</code> if the property was successfully set
298      */

299     public boolean setProperty(String name, String value) {
300         if (protocolHandler == null) {
301             return false;
302         }
303         return IntrospectionUtils.setProperty(protocolHandler, name, value);
304     }
305
306
307     /**
308      * Return a property from the protocol handler.
309      *
310      * @param name the property name
311      * @return the property value
312      */

313     public Object getAttribute(String name) {
314         return getProperty(name);
315     }
316
317
318     /**
319      * Set a property on the protocol handler.
320      *
321      * @param name the property name
322      * @param value the property value
323      */

324     public void setAttribute(String name, Object value) {
325         setProperty(name, String.valueOf(value));
326     }
327
328
329     /**
330      * @return the <code>Service</code> with which we are associated (if any).
331      */

332     public Service getService() {
333         return this.service;
334     }
335
336
337     /**
338      * Set the <code>Service</code> with which we are associated (if any).
339      *
340      * @param service The service that owns this Engine
341      */

342     public void setService(Service service) {
343         this.service = service;
344     }
345
346
347     /**
348      * @return <code>true</code> if the TRACE method is allowed. Default value
349      *         is <code>false</code>.
350      */

351     public boolean getAllowTrace() {
352         return this.allowTrace;
353     }
354
355
356     /**
357      * Set the allowTrace flag, to disable or enable the TRACE HTTP method.
358      *
359      * @param allowTrace The new allowTrace flag
360      */

361     public void setAllowTrace(boolean allowTrace) {
362         this.allowTrace = allowTrace;
363         setProperty("allowTrace", String.valueOf(allowTrace));
364     }
365
366
367     /**
368      * @return the default timeout for async requests in ms.
369      */

370     public long getAsyncTimeout() {
371         return asyncTimeout;
372     }
373
374
375     /**
376      * Set the default timeout for async requests.
377      *
378      * @param asyncTimeout The new timeout in ms.
379      */

380     public void setAsyncTimeout(long asyncTimeout) {
381         this.asyncTimeout= asyncTimeout;
382         setProperty("asyncTimeout", String.valueOf(asyncTimeout));
383     }
384
385
386     /**
387      * @return <code>true</code> if the object facades are discarded, either
388      *   when the discardFacades value is <code>true</code> or when the
389      *   security manager is enabled.
390      */

391     public boolean getDiscardFacades() {
392         return discardFacades || Globals.IS_SECURITY_ENABLED;
393     }
394
395
396     /**
397      * Set the recycling strategy for the object facades.
398      * @param discardFacades the new value of the flag
399      */

400     public void setDiscardFacades(boolean discardFacades) {
401         this.discardFacades = discardFacades;
402     }
403
404
405     /**
406      * @return the "enable DNS lookups" flag.
407      */

408     public boolean getEnableLookups() {
409         return this.enableLookups;
410     }
411
412
413     /**
414      * Set the "enable DNS lookups" flag.
415      *
416      * @param enableLookups The new "enable DNS lookups" flag value
417      */

418     public void setEnableLookups(boolean enableLookups) {
419         this.enableLookups = enableLookups;
420         setProperty("enableLookups", String.valueOf(enableLookups));
421     }
422
423
424     public int getMaxCookieCount() {
425         return maxCookieCount;
426     }
427
428
429     public void setMaxCookieCount(int maxCookieCount) {
430         this.maxCookieCount = maxCookieCount;
431     }
432
433
434     /**
435      * @return the maximum number of parameters (GET plus POST) that will be
436      * automatically parsed by the container. A value of less than 0 means no
437      * limit.
438      */

439     public int getMaxParameterCount() {
440         return maxParameterCount;
441     }
442
443
444     /**
445      * Set the maximum number of parameters (GET plus POST) that will be
446      * automatically parsed by the container. A value of less than 0 means no
447      * limit.
448      *
449      * @param maxParameterCount The new setting
450      */

451     public void setMaxParameterCount(int maxParameterCount) {
452         this.maxParameterCount = maxParameterCount;
453         setProperty("maxParameterCount", String.valueOf(maxParameterCount));
454     }
455
456
457     /**
458      * @return the maximum size of a POST which will be automatically
459      * parsed by the container.
460      */

461     public int getMaxPostSize() {
462         return maxPostSize;
463     }
464
465
466     /**
467      * Set the maximum size of a POST which will be automatically
468      * parsed by the container.
469      *
470      * @param maxPostSize The new maximum size in bytes of a POST which will
471      * be automatically parsed by the container
472      */

473     public void setMaxPostSize(int maxPostSize) {
474         this.maxPostSize = maxPostSize;
475         setProperty("maxPostSize", String.valueOf(maxPostSize));
476     }
477
478
479     /**
480      * @return the maximum size of a POST which will be saved by the container
481      * during authentication.
482      */

483     public int getMaxSavePostSize() {
484         return maxSavePostSize;
485     }
486
487
488     /**
489      * Set the maximum size of a POST which will be saved by the container
490      * during authentication.
491      *
492      * @param maxSavePostSize The new maximum size in bytes of a POST which will
493      * be saved by the container during authentication.
494      */

495     public void setMaxSavePostSize(int maxSavePostSize) {
496         this.maxSavePostSize = maxSavePostSize;
497         setProperty("maxSavePostSize", String.valueOf(maxSavePostSize));
498     }
499
500
501     /**
502      * @return the HTTP methods which will support body parameters parsing
503      */

504     public String getParseBodyMethods() {
505         return this.parseBodyMethods;
506     }
507
508
509     /**
510      * Set list of HTTP methods which should allow body parameter
511      * parsing. This defaults to <code>POST</code>.
512      *
513      * @param methods Comma separated list of HTTP method names
514      */

515     public void setParseBodyMethods(String methods) {
516
517         HashSet<String> methodSet = new HashSet<>();
518
519         if (null != methods) {
520             methodSet.addAll(Arrays.asList(methods.split("\\s*,\\s*")));
521         }
522
523         if (methodSet.contains("TRACE")) {
524             throw new IllegalArgumentException(sm.getString("coyoteConnector.parseBodyMethodNoTrace"));
525         }
526
527         this.parseBodyMethods = methods;
528         this.parseBodyMethodsSet = methodSet;
529         setProperty("parseBodyMethods", methods);
530     }
531
532
533     protected boolean isParseBodyMethod(String method) {
534         return parseBodyMethodsSet.contains(method);
535     }
536
537
538     /**
539      * @return the port number on which this connector is configured to listen
540      * for requests. The special value of 0 means select a random free port
541      * when the socket is bound.
542      */

543     public int getPort() {
544         // Try shortcut that should work for nearly all uses first as it does
545         // not use reflection and is therefore faster.
546         if (protocolHandler instanceof AbstractProtocol<?>) {
547             return ((AbstractProtocol<?>) protocolHandler).getPort();
548         }
549         // Fall back for custom protocol handlers not based on AbstractProtocol
550         Object port = getProperty("port");
551         if (port instanceof Integer) {
552             return ((Integer) port).intValue();
553         }
554         // Usually means an invalid protocol has been configured
555         return -1;
556     }
557
558
559     /**
560      * Set the port number on which we listen for requests.
561      *
562      * @param port The new port number
563      */

564     public void setPort(int port) {
565         setProperty("port", String.valueOf(port));
566     }
567
568
569     public int getPortOffset() {
570         // Try shortcut that should work for nearly all uses first as it does
571         // not use reflection and is therefore faster.
572         if (protocolHandler instanceof AbstractProtocol<?>) {
573             return ((AbstractProtocol<?>) protocolHandler).getPortOffset();
574         }
575         // Fall back for custom protocol handlers not based on AbstractProtocol
576         Object port = getProperty("portOffset");
577         if (port instanceof Integer) {
578             return ((Integer) port).intValue();
579         }
580         // Usually means an invalid protocol has been configured.
581         return 0;
582     }
583
584
585     public void setPortOffset(int portOffset) {
586         setProperty("portOffset", String.valueOf(portOffset));
587     }
588
589
590     public int getPortWithOffset() {
591         int port = getPort();
592         // Zero is a special case and negative values are invalid
593         if (port > 0) {
594             return port + getPortOffset();
595         }
596         return port;
597     }
598
599
600     /**
601      * @return the port number on which this connector is listening to requests.
602      * If the special value for {@link #getPort} of zero is used then this method
603      * will report the actual port bound.
604      */

605     public int getLocalPort() {
606         return ((Integer) getProperty("localPort")).intValue();
607     }
608
609
610     /**
611      * @return the Coyote protocol handler in use.
612      */

613     public String getProtocol() {
614         if (("org.apache.coyote.http11.Http11NioProtocol".equals(getProtocolHandlerClassName()) &&
615                     (!AprLifecycleListener.isAprAvailable() || !AprLifecycleListener.getUseAprConnector())) ||
616                 "org.apache.coyote.http11.Http11AprProtocol".equals(getProtocolHandlerClassName()) &&
617                     AprLifecycleListener.getUseAprConnector()) {
618             return "HTTP/1.1";
619         } else if (("org.apache.coyote.ajp.AjpNioProtocol".equals(getProtocolHandlerClassName()) &&
620                     (!AprLifecycleListener.isAprAvailable() || !AprLifecycleListener.getUseAprConnector())) ||
621                 "org.apache.coyote.ajp.AjpAprProtocol".equals(getProtocolHandlerClassName()) &&
622                     AprLifecycleListener.getUseAprConnector()) {
623             return "AJP/1.3";
624         }
625         return getProtocolHandlerClassName();
626     }
627
628
629     /**
630      * @return the class name of the Coyote protocol handler in use.
631      */

632     public String getProtocolHandlerClassName() {
633         return this.protocolHandlerClassName;
634     }
635
636
637     /**
638      * @return the protocol handler associated with the connector.
639      */

640     public ProtocolHandler getProtocolHandler() {
641         return this.protocolHandler;
642     }
643
644
645     /**
646      * @return the proxy server name for this Connector.
647      */

648     public String getProxyName() {
649         return this.proxyName;
650     }
651
652
653     /**
654      * Set the proxy server name for this Connector.
655      *
656      * @param proxyName The new proxy server name
657      */

658     public void setProxyName(String proxyName) {
659
660         if(proxyName != null && proxyName.length() > 0) {
661             this.proxyName = proxyName;
662         } else {
663             this.proxyName = null;
664         }
665         setProperty("proxyName"this.proxyName);
666     }
667
668
669     /**
670      * @return the proxy server port for this Connector.
671      */

672     public int getProxyPort() {
673         return this.proxyPort;
674     }
675
676
677     /**
678      * Set the proxy server port for this Connector.
679      *
680      * @param proxyPort The new proxy server port
681      */

682     public void setProxyPort(int proxyPort) {
683         this.proxyPort = proxyPort;
684         setProperty("proxyPort", String.valueOf(proxyPort));
685     }
686
687
688     /**
689      * @return the port number to which a request should be redirected if
690      * it comes in on a non-SSL port and is subject to a security constraint
691      * with a transport guarantee that requires SSL.
692      */

693     public int getRedirectPort() {
694         return this.redirectPort;
695     }
696
697
698     /**
699      * Set the redirect port number.
700      *
701      * @param redirectPort The redirect port number (non-SSL to SSL)
702      */

703     public void setRedirectPort(int redirectPort) {
704         this.redirectPort = redirectPort;
705         setProperty("redirectPort", String.valueOf(redirectPort));
706     }
707
708
709     public int getRedirectPortWithOffset() {
710         return getRedirectPort() + getPortOffset();
711     }
712
713
714     /**
715      * @return the scheme that will be assigned to requests received
716      * through this connector.  Default value is "http".
717      */

718     public String getScheme() {
719         return this.scheme;
720     }
721
722
723     /**
724      * Set the scheme that will be assigned to requests received through
725      * this connector.
726      *
727      * @param scheme The new scheme
728      */

729     public void setScheme(String scheme) {
730         this.scheme = scheme;
731     }
732
733
734     /**
735      * @return the secure connection flag that will be assigned to requests
736      * received through this connector.  Default value is "false".
737      */

738     public boolean getSecure() {
739         return this.secure;
740     }
741
742
743     /**
744      * Set the secure connection flag that will be assigned to requests
745      * received through this connector.
746      *
747      * @param secure The new secure connection flag
748      */

749     public void setSecure(boolean secure) {
750         this.secure = secure;
751         setProperty("secure", Boolean.toString(secure));
752     }
753
754
755     /**
756      * @return the name of character encoding to be used for the URI using the
757      * original case.
758      */

759     public String getURIEncoding() {
760         return uriCharset.name();
761     }
762
763
764     /**
765      *
766      * @return The Charset to use to convert raw URI bytes (after %nn decoding)
767      *         to characters. This will never be null
768      */

769     public Charset getURICharset() {
770         return uriCharset;
771     }
772
773     /**
774      * Set the URI encoding to be used for the URI.
775      *
776      * @param URIEncoding The new URI character encoding.
777      */

778     public void setURIEncoding(String URIEncoding) {
779         try {
780             uriCharset = B2CConverter.getCharset(URIEncoding);
781         } catch (UnsupportedEncodingException e) {
782             log.error(sm.getString("coyoteConnector.invalidEncoding",
783                     URIEncoding, uriCharset.name()), e);
784         }
785     }
786
787
788     /**
789      * @return the true if the entity body encoding should be used for the URI.
790      */

791     public boolean getUseBodyEncodingForURI() {
792         return this.useBodyEncodingForURI;
793     }
794
795
796     /**
797      * Set if the entity body encoding should be used for the URI.
798      *
799      * @param useBodyEncodingForURI The new value for the flag.
800      */

801     public void setUseBodyEncodingForURI(boolean useBodyEncodingForURI) {
802         this.useBodyEncodingForURI = useBodyEncodingForURI;
803         setProperty("useBodyEncodingForURI", String.valueOf(useBodyEncodingForURI));
804     }
805
806     /**
807      * Indicates whether the generation of an X-Powered-By response header for
808      * Servlet-generated responses is enabled or disabled for this Connector.
809      *
810      * @return <code>true</code> if generation of X-Powered-By response header is enabled,
811      * false otherwise
812      */

813     public boolean getXpoweredBy() {
814         return xpoweredBy;
815     }
816
817
818     /**
819      * Enables or disables the generation of an X-Powered-By header (with value
820      * Servlet/2.5) for all servlet-generated responses returned by this
821      * Connector.
822      *
823      * @param xpoweredBy true if generation of X-Powered-By response header is
824      * to be enabled, false otherwise
825      */

826     public void setXpoweredBy(boolean xpoweredBy) {
827         this.xpoweredBy = xpoweredBy;
828         setProperty("xpoweredBy", String.valueOf(xpoweredBy));
829     }
830
831
832     /**
833      * Enable the use of IP-based virtual hosting.
834      *
835      * @param useIPVHosts <code>true</code> if Hosts are identified by IP,
836      *                    <code>false</code> if Hosts are identified by name.
837      */

838     public void setUseIPVHosts(boolean useIPVHosts) {
839         this.useIPVHosts = useIPVHosts;
840         setProperty("useIPVHosts", String.valueOf(useIPVHosts));
841     }
842
843
844     /**
845      * Test if IP-based virtual hosting is enabled.
846      *
847      * @return <code>true</code> if IP vhosts are enabled
848      */

849     public boolean getUseIPVHosts() {
850         return useIPVHosts;
851     }
852
853
854     public String getExecutorName() {
855         Object obj = protocolHandler.getExecutor();
856         if (obj instanceof org.apache.catalina.Executor) {
857             return ((org.apache.catalina.Executor) obj).getName();
858         }
859         return INTERNAL_EXECUTOR_NAME;
860     }
861
862
863     public void addSslHostConfig(SSLHostConfig sslHostConfig) {
864         protocolHandler.addSslHostConfig(sslHostConfig);
865     }
866
867
868     public SSLHostConfig[] findSslHostConfigs() {
869         return protocolHandler.findSslHostConfigs();
870     }
871
872
873     public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol) {
874         protocolHandler.addUpgradeProtocol(upgradeProtocol);
875     }
876
877
878     public UpgradeProtocol[] findUpgradeProtocols() {
879         return protocolHandler.findUpgradeProtocols();
880     }
881
882
883     // --------------------------------------------------------- Public Methods
884
885     /**
886      * Create (or allocate) and return a Request object suitable for
887      * specifying the contents of a Request to the responsible Container.
888      *
889      * @return a new Servlet request object
890      */

891     public Request createRequest() {
892         return new Request(this);
893     }
894
895
896     /**
897      * Create (or allocate) and return a Response object suitable for
898      * receiving the contents of a Response from the responsible Container.
899      *
900      * @return a new Servlet response object
901      */

902     public Response createResponse() {
903         if (protocolHandler instanceof AbstractAjpProtocol<?>) {
904             int packetSize = ((AbstractAjpProtocol<?>) protocolHandler).getPacketSize();
905             return new Response(packetSize - org.apache.coyote.ajp.Constants.SEND_HEAD_LEN);
906         } else {
907             return new Response();
908         }
909     }
910
911
912     protected String createObjectNameKeyProperties(String type) {
913
914         Object addressObj = getProperty("address");
915
916         StringBuilder sb = new StringBuilder("type=");
917         sb.append(type);
918         sb.append(",port=");
919         int port = getPortWithOffset();
920         if (port > 0) {
921             sb.append(port);
922         } else {
923             sb.append("auto-");
924             sb.append(getProperty("nameIndex"));
925         }
926         String address = "";
927         if (addressObj instanceof InetAddress) {
928             address = ((InetAddress) addressObj).getHostAddress();
929         } else if (addressObj != null) {
930             address = addressObj.toString();
931         }
932         if (address.length() > 0) {
933             sb.append(",address=");
934             sb.append(ObjectName.quote(address));
935         }
936         return sb.toString();
937     }
938
939
940     /**
941      * Pause the connector.
942      */

943     public void pause() {
944         try {
945             if (protocolHandler != null) {
946                 protocolHandler.pause();
947             }
948         } catch (Exception e) {
949             log.error(sm.getString("coyoteConnector.protocolHandlerPauseFailed"), e);
950         }
951     }
952
953
954     /**
955      * Resume the connector.
956      */

957     public void resume() {
958         try {
959             if (protocolHandler != null) {
960                 protocolHandler.resume();
961             }
962         } catch (Exception e) {
963             log.error(sm.getString("coyoteConnector.protocolHandlerResumeFailed"), e);
964         }
965     }
966
967
968     @Override
969     protected void initInternal() throws LifecycleException {
970
971         super.initInternal();
972
973         if (protocolHandler == null) {
974             throw new LifecycleException(
975                     sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
976         }
977
978         // Initialize adapter
979         adapter = new CoyoteAdapter(this);
980         protocolHandler.setAdapter(adapter);
981         if (service != null) {
982             protocolHandler.setUtilityExecutor(service.getServer().getUtilityExecutor());
983         }
984
985         // Make sure parseBodyMethodsSet has a default
986         if (null == parseBodyMethodsSet) {
987             setParseBodyMethods(getParseBodyMethods());
988         }
989
990         if (protocolHandler.isAprRequired() && !AprLifecycleListener.isInstanceCreated()) {
991             throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
992                     getProtocolHandlerClassName()));
993         }
994         if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
995             throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
996                     getProtocolHandlerClassName()));
997         }
998         if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
999                 protocolHandler instanceof AbstractHttp11JsseProtocol) {
1000             AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
1001                     (AbstractHttp11JsseProtocol<?>) protocolHandler;
1002             if (jsseProtocolHandler.isSSLEnabled() &&
1003                     jsseProtocolHandler.getSslImplementationName() == null) {
1004                 // OpenSSL is compatible with the JSSE configuration, so use it if APR is available
1005                 jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
1006             }
1007         }
1008
1009         try {
1010             protocolHandler.init();
1011         } catch (Exception e) {
1012             throw new LifecycleException(
1013                     sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
1014         }
1015     }
1016
1017
1018     /**
1019      * Begin processing requests via this Connector.
1020      *
1021      * @exception LifecycleException if a fatal startup error occurs
1022      */

1023     @Override
1024     protected void startInternal() throws LifecycleException {
1025
1026         // Validate settings before starting
1027         if (getPortWithOffset() < 0) {
1028             throw new LifecycleException(sm.getString(
1029                     "coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));
1030         }
1031
1032         setState(LifecycleState.STARTING);
1033
1034         try {
1035             protocolHandler.start();
1036         } catch (Exception e) {
1037             throw new LifecycleException(
1038                     sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
1039         }
1040     }
1041
1042
1043     /**
1044      * Terminate processing requests via this Connector.
1045      *
1046      * @exception LifecycleException if a fatal shutdown error occurs
1047      */

1048     @Override
1049     protected void stopInternal() throws LifecycleException {
1050
1051         setState(LifecycleState.STOPPING);
1052
1053         try {
1054             if (protocolHandler != null) {
1055                 protocolHandler.stop();
1056             }
1057         } catch (Exception e) {
1058             throw new LifecycleException(
1059                     sm.getString("coyoteConnector.protocolHandlerStopFailed"), e);
1060         }
1061     }
1062
1063
1064     @Override
1065     protected void destroyInternal() throws LifecycleException {
1066         try {
1067             if (protocolHandler != null) {
1068                 protocolHandler.destroy();
1069             }
1070         } catch (Exception e) {
1071             throw new LifecycleException(
1072                     sm.getString("coyoteConnector.protocolHandlerDestroyFailed"), e);
1073         }
1074
1075         if (getService() != null) {
1076             getService().removeConnector(this);
1077         }
1078
1079         super.destroyInternal();
1080     }
1081
1082
1083     /**
1084      * Provide a useful toString() implementation as it may be used when logging
1085      * Lifecycle errors to identify the component.
1086      */

1087     @Override
1088     public String toString() {
1089         // Not worth caching this right now
1090         StringBuilder sb = new StringBuilder("Connector[");
1091         sb.append(getProtocol());
1092         sb.append('-');
1093         int port = getPortWithOffset();
1094         if (port > 0) {
1095             sb.append(port);
1096         } else {
1097             sb.append("auto-");
1098             sb.append(getProperty("nameIndex"));
1099         }
1100         sb.append(']');
1101         return sb.toString();
1102     }
1103
1104
1105     // -------------------- JMX registration  --------------------
1106
1107     @Override
1108     protected String getDomainInternal() {
1109         Service s = getService();
1110         if (s == null) {
1111             return null;
1112         } else {
1113             return service.getDomain();
1114         }
1115     }
1116
1117     @Override
1118     protected String getObjectNameKeyProperties() {
1119         return createObjectNameKeyProperties("Connector");
1120     }
1121
1122 }
1123