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
18
19 package org.apache.catalina.connector;
20
21 import java.lang.reflect.Method;
22 import java.net.URLEncoder;
23 import java.util.HashMap;
24
25 import javax.management.MBeanRegistration;
26 import javax.management.MBeanServer;
27 import javax.management.MalformedObjectNameException;
28 import javax.management.ObjectName;
29
30 import org.apache.catalina.Container;
31 import org.apache.catalina.Lifecycle;
32 import org.apache.catalina.LifecycleException;
33 import org.apache.catalina.LifecycleListener;
34 import org.apache.catalina.Service;
35 import org.apache.catalina.core.StandardEngine;
36 import org.apache.catalina.util.LifecycleSupport;
37 import org.apache.catalina.util.StringManager;
38 import org.apache.coyote.Adapter;
39 import org.apache.coyote.ProtocolHandler;
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.http.mapper.Mapper;
44 import org.apache.tomcat.util.modeler.Registry;
45
46
47 /**
48 * Implementation of a Coyote connector for Tomcat 5.x.
49 *
50 * @author Craig R. McClanahan
51 * @author Remy Maucherat
52 * @version $Revision: 586738 $ $Date: 2007-10-20 16:57:18 +0200 (sam., 20 oct. 2007) $
53 */
54
55
56 public class Connector
57 implements Lifecycle, MBeanRegistration
58 {
59 private static Log log = LogFactory.getLog(Connector.class);
60
61
62 /**
63 * Alternate flag to enable recycling of facades.
64 */
65 public static final boolean RECYCLE_FACADES =
66 Boolean.valueOf(System.getProperty("org.apache.catalina.connector.RECYCLE_FACADES", "false")).booleanValue();
67
68
69 // ------------------------------------------------------------ Constructor
70
71
72 public Connector()
73 throws Exception {
74 this(null);
75 }
76
77 public Connector(String protocol)
78 throws Exception {
79 setProtocol(protocol);
80 // Instantiate protocol handler
81 try {
82 Class clazz = Class.forName(protocolHandlerClassName);
83 this.protocolHandler = (ProtocolHandler) clazz.newInstance();
84 } catch (Exception e) {
85 log.error
86 (sm.getString
87 ("coyoteConnector.protocolHandlerInstantiationFailed", e));
88 }
89 }
90
91
92 // ----------------------------------------------------- Instance Variables
93
94
95 /**
96 * The <code>Service</code> we are associated with (if any).
97 */
98 protected Service service = null;
99
100
101 /**
102 * Do we allow TRACE ?
103 */
104 protected boolean allowTrace = false;
105
106
107 /**
108 * The Container used for processing requests received by this Connector.
109 */
110 protected Container container = null;
111
112
113 /**
114 * Use "/" as path for session cookies ?
115 */
116 protected boolean emptySessionPath = false;
117
118
119 /**
120 * The "enable DNS lookups" flag for this Connector.
121 */
122 protected boolean enableLookups = false;
123
124
125 /*
126 * Is generation of X-Powered-By response header enabled/disabled?
127 */
128 protected boolean xpoweredBy = false;
129
130
131 /**
132 * Descriptive information about this Connector implementation.
133 */
134 protected static final String info =
135 "org.apache.catalina.connector.Connector/2.1";
136
137
138 /**
139 * The lifecycle event support for this component.
140 */
141 protected LifecycleSupport lifecycle = new LifecycleSupport(this);
142
143
144 /**
145 * The port number on which we listen for requests.
146 */
147 protected int port = 0;
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 pretent 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 redirect port for non-SSL to SSL redirects.
170 */
171 protected int redirectPort = 443;
172
173
174 /**
175 * The request scheme that will be set on all requests received
176 * through this connector.
177 */
178 protected String scheme = "http";
179
180
181 /**
182 * The secure connection flag that will be set on all requests received
183 * through this connector.
184 */
185 protected boolean secure = false;
186
187
188 /**
189 * The string manager for this package.
190 */
191 protected StringManager sm =
192 StringManager.getManager(Constants.Package);
193
194
195 /**
196 * Maximum size of a POST which will be automatically parsed by the
197 * container. 2MB by default.
198 */
199 protected int maxPostSize = 2 * 1024 * 1024;
200
201
202 /**
203 * Maximum size of a POST which will be saved by the container
204 * during authentication. 4kB by default
205 */
206 protected int maxSavePostSize = 4 * 1024;
207
208
209 /**
210 * Has this component been initialized yet?
211 */
212 protected boolean initialized = false;
213
214
215 /**
216 * Has this component been started yet?
217 */
218 protected boolean started = false;
219
220
221 /**
222 * The shutdown signal to our background thread
223 */
224 protected boolean stopped = false;
225
226 /**
227 * Flag to use IP-based virtual hosting.
228 */
229 protected boolean useIPVHosts = false;
230
231 /**
232 * The background thread.
233 */
234 protected Thread thread = null;
235
236
237 /**
238 * Coyote Protocol handler class name.
239 * Defaults to the Coyote HTTP/1.1 protocolHandler.
240 */
241 protected String protocolHandlerClassName =
242 "org.apache.coyote.http11.Http11Protocol";
243
244
245 /**
246 * Coyote protocol handler.
247 */
248 protected ProtocolHandler protocolHandler = null;
249
250
251 /**
252 * Coyote adapter.
253 */
254 protected Adapter adapter = null;
255
256
257 /**
258 * Mapper.
259 */
260 protected Mapper mapper = new Mapper();
261
262
263 /**
264 * Mapper listener.
265 */
266 protected MapperListener mapperListener = new MapperListener(mapper);
267
268
269 /**
270 * URI encoding.
271 */
272 protected String URIEncoding = null;
273
274
275 /**
276 * URI encoding as body.
277 */
278 protected boolean useBodyEncodingForURI = false;
279
280
281 protected static HashMap replacements = new HashMap();
282 static {
283 replacements.put("acceptCount", "backlog");
284 replacements.put("connectionLinger", "soLinger");
285 replacements.put("connectionTimeout", "soTimeout");
286 replacements.put("connectionUploadTimeout", "timeout");
287 replacements.put("clientAuth", "clientauth");
288 replacements.put("keystoreFile", "keystore");
289 replacements.put("randomFile", "randomfile");
290 replacements.put("rootFile", "rootfile");
291 replacements.put("keystorePass", "keypass");
292 replacements.put("keystoreType", "keytype");
293 replacements.put("sslProtocol", "protocol");
294 replacements.put("sslProtocols", "protocols");
295 }
296
297
298 // ------------------------------------------------------------- Properties
299
300
301 /**
302 * Return a configured property.
303 */
304 public Object getProperty(String name) {
305 String repl = name;
306 if (replacements.get(name) != null) {
307 repl = (String) replacements.get(name);
308 }
309 return IntrospectionUtils.getProperty(protocolHandler, repl);
310 }
311
312
313 /**
314 * Set a configured property.
315 */
316 public boolean setProperty(String name, String value) {
317 String repl = name;
318 if (replacements.get(name) != null) {
319 repl = (String) replacements.get(name);
320 }
321 return IntrospectionUtils.setProperty(protocolHandler, repl, value);
322 }
323
324 /**
325 * Return a configured property.
326 */
327 public Object getAttribute(String name) {
328 return getProperty(name);
329 }
330
331
332 /**
333 * Set a configured property.
334 */
335 public void setAttribute(String name, Object value) {
336 setProperty(name, String.valueOf(value));
337 }
338
339
340 /**
341 * remove a configured property.
342 */
343 public void removeProperty(String name) {
344 // FIXME !
345 //protocolHandler.removeAttribute(name);
346 }
347
348
349 /**
350 * Return the <code>Service</code> with which we are associated (if any).
351 */
352 public Service getService() {
353
354 return (this.service);
355
356 }
357
358
359 /**
360 * Set the <code>Service</code> with which we are associated (if any).
361 *
362 * @param service The service that owns this Engine
363 */
364 public void setService(Service service) {
365
366 this.service = service;
367 // FIXME: setProperty("service", service);
368
369 }
370
371
372 /**
373 * True if the TRACE method is allowed. Default value is "false".
374 */
375 public boolean getAllowTrace() {
376
377 return (this.allowTrace);
378
379 }
380
381
382 /**
383 * Set the allowTrace flag, to disable or enable the TRACE HTTP method.
384 *
385 * @param allowTrace The new allowTrace flag
386 */
387 public void setAllowTrace(boolean allowTrace) {
388
389 this.allowTrace = allowTrace;
390 setProperty("allowTrace", String.valueOf(allowTrace));
391
392 }
393
394 /**
395 * Is this connector available for processing requests?
396 */
397 public boolean isAvailable() {
398
399 return (started);
400
401 }
402
403
404 /**
405 * Return the input buffer size for this Connector.
406 *
407 * @deprecated
408 */
409 public int getBufferSize() {
410 return 2048;
411 }
412
413 /**
414 * Set the input buffer size for this Connector.
415 *
416 * @param bufferSize The new input buffer size.
417 * @deprecated
418 */
419 public void setBufferSize(int bufferSize) {
420 }
421
422
423 /**
424 * Return the Container used for processing requests received by this
425 * Connector.
426 */
427 public Container getContainer() {
428 if( container==null ) {
429 // Lazy - maybe it was added later
430 findContainer();
431 }
432 return (container);
433
434 }
435
436
437 /**
438 * Set the Container used for processing requests received by this
439 * Connector.
440 *
441 * @param container The new Container to use
442 */
443 public void setContainer(Container container) {
444
445 this.container = container;
446
447 }
448
449
450 /**
451 * Return the "empty session path" flag.
452 */
453 public boolean getEmptySessionPath() {
454
455 return (this.emptySessionPath);
456
457 }
458
459
460 /**
461 * Set the "empty session path" flag.
462 *
463 * @param emptySessionPath The new "empty session path" flag value
464 */
465 public void setEmptySessionPath(boolean emptySessionPath) {
466
467 this.emptySessionPath = emptySessionPath;
468 setProperty("emptySessionPath", String.valueOf(emptySessionPath));
469
470 }
471
472
473 /**
474 * Return the "enable DNS lookups" flag.
475 */
476 public boolean getEnableLookups() {
477
478 return (this.enableLookups);
479
480 }
481
482
483 /**
484 * Set the "enable DNS lookups" flag.
485 *
486 * @param enableLookups The new "enable DNS lookups" flag value
487 */
488 public void setEnableLookups(boolean enableLookups) {
489
490 this.enableLookups = enableLookups;
491 setProperty("enableLookups", String.valueOf(enableLookups));
492
493 }
494
495
496 /**
497 * Return descriptive information about this Connector implementation.
498 */
499 public String getInfo() {
500
501 return (info);
502
503 }
504
505
506 /**
507 * Return the mapper.
508 */
509 public Mapper getMapper() {
510
511 return (mapper);
512
513 }
514
515
516 /**
517 * Return the maximum size of a POST which will be automatically
518 * parsed by the container.
519 */
520 public int getMaxPostSize() {
521
522 return (maxPostSize);
523
524 }
525
526
527 /**
528 * Set the maximum size of a POST which will be automatically
529 * parsed by the container.
530 *
531 * @param maxPostSize The new maximum size in bytes of a POST which will
532 * be automatically parsed by the container
533 */
534 public void setMaxPostSize(int maxPostSize) {
535
536 this.maxPostSize = maxPostSize;
537 }
538
539
540 /**
541 * Return the maximum size of a POST which will be saved by the container
542 * during authentication.
543 */
544 public int getMaxSavePostSize() {
545
546 return (maxSavePostSize);
547
548 }
549
550
551 /**
552 * Set the maximum size of a POST which will be saved by the container
553 * during authentication.
554 *
555 * @param maxSavePostSize The new maximum size in bytes of a POST which will
556 * be saved by the container during authentication.
557 */
558 public void setMaxSavePostSize(int maxSavePostSize) {
559
560 this.maxSavePostSize = maxSavePostSize;
561 setProperty("maxSavePostSize", String.valueOf(maxSavePostSize));
562 }
563
564
565 /**
566 * Return the port number on which we listen for requests.
567 */
568 public int getPort() {
569
570 return (this.port);
571
572 }
573
574
575 /**
576 * Set the port number on which we listen for requests.
577 *
578 * @param port The new port number
579 */
580 public void setPort(int port) {
581
582 this.port = port;
583 setProperty("port", String.valueOf(port));
584
585 }
586
587
588 /**
589 * Return the Coyote protocol handler in use.
590 */
591 public String getProtocol() {
592
593 if ("org.apache.coyote.http11.Http11Protocol".equals
594 (getProtocolHandlerClassName())
595 || "org.apache.coyote.http11.Http11AprProtocol".equals
596 (getProtocolHandlerClassName())) {
597 return "HTTP/1.1";
598 } else if ("org.apache.jk.server.JkCoyoteHandler".equals
599 (getProtocolHandlerClassName())
600 || "org.apache.coyote.ajp.AjpAprProtocol".equals
601 (getProtocolHandlerClassName())) {
602 return "AJP/1.3";
603 }
604 return getProtocolHandlerClassName();
605
606 }
607
608 // ---------------------------------------------- APR Version Constants
609
610 private static final int TCN_REQUIRED_MAJOR = 1;
611 private static final int TCN_REQUIRED_MINOR = 1;
612 private static final int TCN_REQUIRED_PATCH = 3;
613 private static boolean aprInitialized = false;
614
615 // APR init support
616 private static synchronized void initializeAPR()
617 {
618 if (aprInitialized) {
619 return;
620 }
621 int major = 0;
622 int minor = 0;
623 int patch = 0;
624 try {
625 String methodName = "initialize";
626 Class paramTypes[] = new Class[1];
627 paramTypes[0] = String.class;
628 Object paramValues[] = new Object[1];
629 paramValues[0] = null;
630 Class clazz = Class.forName("org.apache.tomcat.jni.Library");
631 Method method = clazz.getMethod(methodName, paramTypes);
632 method.invoke(null, paramValues);
633 major = clazz.getField("TCN_MAJOR_VERSION").getInt(null);
634 minor = clazz.getField("TCN_MINOR_VERSION").getInt(null);
635 patch = clazz.getField("TCN_PATCH_VERSION").getInt(null);
636 } catch (Throwable t) {
637 return;
638 }
639 if ((major != TCN_REQUIRED_MAJOR) ||
640 (minor != TCN_REQUIRED_MINOR) ||
641 (patch < TCN_REQUIRED_PATCH)) {
642 try {
643 // Terminate the APR in case the version
644 // is below required.
645 String methodName = "terminate";
646 Method method = Class.forName("org.apache.tomcat.jni.Library")
647 .getMethod(methodName, (Class [])null);
648 method.invoke(null, (Object []) null);
649 } catch (Throwable t) {
650 // Ignore
651 }
652 return;
653 }
654 aprInitialized = true;
655 }
656
657 /**
658 * Set the Coyote protocol which will be used by the connector.
659 *
660 * @param protocol The Coyote protocol name
661 */
662 public void setProtocol(String protocol) {
663
664 // Test APR support
665 initializeAPR();
666
667 if (aprInitialized) {
668 if ("HTTP/1.1".equals(protocol)) {
669 setProtocolHandlerClassName
670 ("org.apache.coyote.http11.Http11AprProtocol");
671 } else if ("AJP/1.3".equals(protocol)) {
672 setProtocolHandlerClassName
673 ("org.apache.coyote.ajp.AjpAprProtocol");
674 } else if (protocol != null) {
675 setProtocolHandlerClassName(protocol);
676 } else {
677 setProtocolHandlerClassName
678 ("org.apache.coyote.http11.Http11AprProtocol");
679 }
680 } else {
681 if ("HTTP/1.1".equals(protocol)) {
682 setProtocolHandlerClassName
683 ("org.apache.coyote.http11.Http11Protocol");
684 } else if ("AJP/1.3".equals(protocol)) {
685 setProtocolHandlerClassName
686 ("org.apache.jk.server.JkCoyoteHandler");
687 } else if (protocol != null) {
688 setProtocolHandlerClassName(protocol);
689 }
690 }
691
692 }
693
694
695 /**
696 * Return the class name of the Coyote protocol handler in use.
697 */
698 public String getProtocolHandlerClassName() {
699
700 return (this.protocolHandlerClassName);
701
702 }
703
704
705 /**
706 * Set the class name of the Coyote protocol handler which will be used
707 * by the connector.
708 *
709 * @param protocolHandlerClassName The new class name
710 */
711 public void setProtocolHandlerClassName(String protocolHandlerClassName) {
712
713 this.protocolHandlerClassName = protocolHandlerClassName;
714
715 }
716
717
718 /**
719 * Return the protocol handler associated with the connector.
720 */
721 public ProtocolHandler getProtocolHandler() {
722
723 return (this.protocolHandler);
724
725 }
726
727
728 /**
729 * Return the proxy server name for this Connector.
730 */
731 public String getProxyName() {
732
733 return (this.proxyName);
734
735 }
736
737
738 /**
739 * Set the proxy server name for this Connector.
740 *
741 * @param proxyName The new proxy server name
742 */
743 public void setProxyName(String proxyName) {
744
745 if(proxyName != null && proxyName.length() > 0) {
746 this.proxyName = proxyName;
747 setProperty("proxyName", proxyName);
748 } else {
749 this.proxyName = null;
750 removeProperty("proxyName");
751 }
752
753 }
754
755
756 /**
757 * Return the proxy server port for this Connector.
758 */
759 public int getProxyPort() {
760
761 return (this.proxyPort);
762
763 }
764
765
766 /**
767 * Set the proxy server port for this Connector.
768 *
769 * @param proxyPort The new proxy server port
770 */
771 public void setProxyPort(int proxyPort) {
772
773 this.proxyPort = proxyPort;
774 setProperty("proxyPort", String.valueOf(proxyPort));
775
776 }
777
778
779 /**
780 * Return the port number to which a request should be redirected if
781 * it comes in on a non-SSL port and is subject to a security constraint
782 * with a transport guarantee that requires SSL.
783 */
784 public int getRedirectPort() {
785
786 return (this.redirectPort);
787
788 }
789
790
791 /**
792 * Set the redirect port number.
793 *
794 * @param redirectPort The redirect port number (non-SSL to SSL)
795 */
796 public void setRedirectPort(int redirectPort) {
797
798 this.redirectPort = redirectPort;
799 setProperty("redirectPort", String.valueOf(redirectPort));
800
801 }
802
803
804 /**
805 * Return the scheme that will be assigned to requests received
806 * through this connector. Default value is "http".
807 */
808 public String getScheme() {
809
810 return (this.scheme);
811
812 }
813
814
815 /**
816 * Set the scheme that will be assigned to requests received through
817 * this connector.
818 *
819 * @param scheme The new scheme
820 */
821 public void setScheme(String scheme) {
822
823 this.scheme = scheme;
824
825 }
826
827
828 /**
829 * Return the secure connection flag that will be assigned to requests
830 * received through this connector. Default value is "false".
831 */
832 public boolean getSecure() {
833
834 return (this.secure);
835
836 }
837
838
839 /**
840 * Set the secure connection flag that will be assigned to requests
841 * received through this connector.
842 *
843 * @param secure The new secure connection flag
844 */
845 public void setSecure(boolean secure) {
846
847 this.secure = secure;
848 setProperty("secure", Boolean.toString(secure));
849 }
850
851 /**
852 * Return the character encoding to be used for the URI.
853 */
854 public String getURIEncoding() {
855
856 return (this.URIEncoding);
857
858 }
859
860
861 /**
862 * Set the URI encoding to be used for the URI.
863 *
864 * @param URIEncoding The new URI character encoding.
865 */
866 public void setURIEncoding(String URIEncoding) {
867
868 this.URIEncoding = URIEncoding;
869 setProperty("uRIEncoding", URIEncoding);
870
871 }
872
873
874 /**
875 * Return the true if the entity body encoding should be used for the URI.
876 */
877 public boolean getUseBodyEncodingForURI() {
878
879 return (this.useBodyEncodingForURI);
880
881 }
882
883
884 /**
885 * Set if the entity body encoding should be used for the URI.
886 *
887 * @param useBodyEncodingForURI The new value for the flag.
888 */
889 public void setUseBodyEncodingForURI(boolean useBodyEncodingForURI) {
890
891 this.useBodyEncodingForURI = useBodyEncodingForURI;
892 setProperty
893 ("useBodyEncodingForURI", String.valueOf(useBodyEncodingForURI));
894
895 }
896
897
898 /**
899 * Indicates whether the generation of an X-Powered-By response header for
900 * servlet-generated responses is enabled or disabled for this Connector.
901 *
902 * @return true if generation of X-Powered-By response header is enabled,
903 * false otherwise
904 */
905 public boolean getXpoweredBy() {
906 return xpoweredBy;
907 }
908
909
910 /**
911 * Enables or disables the generation of an X-Powered-By header (with value
912 * Servlet/2.5) for all servlet-generated responses returned by this
913 * Connector.
914 *
915 * @param xpoweredBy true if generation of X-Powered-By response header is
916 * to be enabled, false otherwise
917 */
918 public void setXpoweredBy(boolean xpoweredBy) {
919 this.xpoweredBy = xpoweredBy;
920 setProperty("xpoweredBy", String.valueOf(xpoweredBy));
921 }
922
923 /**
924 * Enable the use of IP-based virtual hosting.
925 *
926 * @param useIPVHosts <code>true</code> if Hosts are identified by IP,
927 * <code>false/code> if Hosts are identified by name.
928 */
929 public void setUseIPVHosts(boolean useIPVHosts) {
930 this.useIPVHosts = useIPVHosts;
931 setProperty("useIPVHosts", String.valueOf(useIPVHosts));
932 }
933
934 /**
935 * Test if IP-based virtual hosting is enabled.
936 */
937 public boolean getUseIPVHosts() {
938 return useIPVHosts;
939 }
940
941 // --------------------------------------------------------- Public Methods
942
943
944 /**
945 * Create (or allocate) and return a Request object suitable for
946 * specifying the contents of a Request to the responsible Container.
947 */
948 public Request createRequest() {
949
950 Request request = new Request();
951 request.setConnector(this);
952 return (request);
953
954 }
955
956
957 /**
958 * Create (or allocate) and return a Response object suitable for
959 * receiving the contents of a Response from the responsible Container.
960 */
961 public Response createResponse() {
962
963 Response response = new Response();
964 response.setConnector(this);
965 return (response);
966
967 }
968
969
970 // ------------------------------------------------------ Lifecycle Methods
971
972
973 /**
974 * Add a lifecycle event listener to this component.
975 *
976 * @param listener The listener to add
977 */
978 public void addLifecycleListener(LifecycleListener listener) {
979
980 lifecycle.addLifecycleListener(listener);
981
982 }
983
984
985 /**
986 * Get the lifecycle listeners associated with this lifecycle. If this
987 * Lifecycle has no listeners registered, a zero-length array is returned.
988 */
989 public LifecycleListener[] findLifecycleListeners() {
990
991 return lifecycle.findLifecycleListeners();
992
993 }
994
995
996 /**
997 * Remove a lifecycle event listener from this component.
998 *
999 * @param listener The listener to add
1000 */
1001 public void removeLifecycleListener(LifecycleListener listener) {
1002
1003 lifecycle.removeLifecycleListener(listener);
1004
1005 }
1006
1007
1008 protected ObjectName createObjectName(String domain, String type)
1009 throws MalformedObjectNameException {
1010 String encodedAddr = null;
1011 if (getProperty("address") != null) {
1012 encodedAddr = URLEncoder.encode(getProperty("address").toString());
1013 }
1014 String addSuffix = (getProperty("address") == null) ? "" : ",address="
1015 + encodedAddr;
1016 ObjectName _oname = new ObjectName(domain + ":type=" + type + ",port="
1017 + getPort() + addSuffix);
1018 return _oname;
1019 }
1020
1021 /**
1022 * Initialize this connector (create ServerSocket here!)
1023 */
1024 public void initialize()
1025 throws LifecycleException
1026 {
1027 if (initialized) {
1028 if(log.isInfoEnabled())
1029 log.info(sm.getString("coyoteConnector.alreadyInitialized"));
1030 return;
1031 }
1032
1033 this.initialized = true;
1034
1035 if( oname == null && (container instanceof StandardEngine)) {
1036 try {
1037 // we are loaded directly, via API - and no name was given to us
1038 StandardEngine cb=(StandardEngine)container;
1039 oname = createObjectName(cb.getName(), "Connector");
1040 Registry.getRegistry(null, null)
1041 .registerComponent(this, oname, null);
1042 controller=oname;
1043 } catch (Exception e) {
1044 log.error( "Error registering connector ", e);
1045 }
1046 if(log.isDebugEnabled())
1047 log.debug("Creating name for connector " + oname);
1048 }
1049
1050 // Initializa adapter
1051 adapter = new CoyoteAdapter(this);
1052 protocolHandler.setAdapter(adapter);
1053
1054 IntrospectionUtils.setProperty(protocolHandler, "jkHome",
1055 System.getProperty("catalina.base"));
1056
1057 try {
1058 protocolHandler.init();
1059 } catch (Exception e) {
1060 throw new LifecycleException
1061 (sm.getString
1062 ("coyoteConnector.protocolHandlerInitializationFailed", e));
1063 }
1064 }
1065
1066
1067 /**
1068 * Pause the connector.
1069 */
1070 public void pause()
1071 throws LifecycleException {
1072 try {
1073 protocolHandler.pause();
1074 } catch (Exception e) {
1075 log.error(sm.getString
1076 ("coyoteConnector.protocolHandlerPauseFailed"), e);
1077 }
1078 }
1079
1080
1081 /**
1082 * Pause the connector.
1083 */
1084 public void resume()
1085 throws LifecycleException {
1086 try {
1087 protocolHandler.resume();
1088 } catch (Exception e) {
1089 log.error(sm.getString
1090 ("coyoteConnector.protocolHandlerResumeFailed"), e);
1091 }
1092 }
1093
1094
1095 /**
1096 * Begin processing requests via this Connector.
1097 *
1098 * @exception LifecycleException if a fatal startup error occurs
1099 */
1100 public void start() throws LifecycleException {
1101 if( !initialized )
1102 initialize();
1103
1104 // Validate and update our current state
1105 if (started ) {
1106 if(log.isInfoEnabled())
1107 log.info(sm.getString("coyoteConnector.alreadyStarted"));
1108 return;
1109 }
1110 lifecycle.fireLifecycleEvent(START_EVENT, null);
1111 started = true;
1112
1113 // We can't register earlier - the JMX registration of this happens
1114 // in Server.start callback
1115 if ( this.oname != null ) {
1116 // We are registred - register the adapter as well.
1117 try {
1118 Registry.getRegistry(null, null).registerComponent
1119 (protocolHandler, createObjectName(this.domain,"ProtocolHandler"), null);
1120 } catch (Exception ex) {
1121 log.error(sm.getString
1122 ("coyoteConnector.protocolRegistrationFailed"), ex);
1123 }
1124 } else {
1125 if(log.isInfoEnabled())
1126 log.info(sm.getString
1127 ("coyoteConnector.cannotRegisterProtocol"));
1128 }
1129
1130 try {
1131 protocolHandler.start();
1132 } catch (Exception e) {
1133 String errPrefix = "";
1134 if(this.service != null) {
1135 errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
1136 }
1137
1138 throw new LifecycleException
1139 (errPrefix + " " + sm.getString
1140 ("coyoteConnector.protocolHandlerStartFailed", e));
1141 }
1142
1143 if( this.domain != null ) {
1144 mapperListener.setDomain( domain );
1145 //mapperListener.setEngine( service.getContainer().getName() );
1146 mapperListener.init();
1147 try {
1148 ObjectName mapperOname = createObjectName(this.domain,"Mapper");
1149 if (log.isDebugEnabled())
1150 log.debug(sm.getString(
1151 "coyoteConnector.MapperRegistration", mapperOname));
1152 Registry.getRegistry(null, null).registerComponent
1153 (mapper, mapperOname, "Mapper");
1154 } catch (Exception ex) {
1155 log.error(sm.getString
1156 ("coyoteConnector.protocolRegistrationFailed"), ex);
1157 }
1158 }
1159 }
1160
1161
1162 /**
1163 * Terminate processing requests via this Connector.
1164 *
1165 * @exception LifecycleException if a fatal shutdown error occurs
1166 */
1167 public void stop() throws LifecycleException {
1168
1169 // Validate and update our current state
1170 if (!started) {
1171 log.error(sm.getString("coyoteConnector.notStarted"));
1172 return;
1173
1174 }
1175 lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1176 started = false;
1177
1178 try {
1179 mapperListener.destroy();
1180 Registry.getRegistry(null, null).unregisterComponent
1181 (createObjectName(this.domain,"Mapper"));
1182 Registry.getRegistry(null, null).unregisterComponent
1183 (createObjectName(this.domain,"ProtocolHandler"));
1184 } catch (MalformedObjectNameException e) {
1185 log.error( sm.getString
1186 ("coyoteConnector.protocolUnregistrationFailed"), e);
1187 }
1188 try {
1189 protocolHandler.destroy();
1190 } catch (Exception e) {
1191 throw new LifecycleException
1192 (sm.getString
1193 ("coyoteConnector.protocolHandlerDestroyFailed", e));
1194 }
1195
1196 }
1197
1198
1199 // -------------------- JMX registration --------------------
1200 protected String domain;
1201 protected ObjectName oname;
1202 protected MBeanServer mserver;
1203 ObjectName controller;
1204
1205 public ObjectName getController() {
1206 return controller;
1207 }
1208
1209 public void setController(ObjectName controller) {
1210 this.controller = controller;
1211 }
1212
1213 public ObjectName getObjectName() {
1214 return oname;
1215 }
1216
1217 public String getDomain() {
1218 return domain;
1219 }
1220
1221 public ObjectName preRegister(MBeanServer server,
1222 ObjectName name) throws Exception {
1223 oname=name;
1224 mserver=server;
1225 domain=name.getDomain();
1226 return name;
1227 }
1228
1229 public void postRegister(Boolean registrationDone) {
1230 }
1231
1232 public void preDeregister() throws Exception {
1233 }
1234
1235 public void postDeregister() {
1236 try {
1237 if( started ) {
1238 stop();
1239 }
1240 } catch( Throwable t ) {
1241 log.error( "Unregistering - can't stop", t);
1242 }
1243 }
1244
1245 protected void findContainer() {
1246 try {
1247 // Register to the service
1248 ObjectName parentName=new ObjectName( domain + ":" +
1249 "type=Service");
1250
1251 if(log.isDebugEnabled())
1252 log.debug("Adding to " + parentName );
1253 if( mserver.isRegistered(parentName )) {
1254 mserver.invoke(parentName, "addConnector", new Object[] { this },
1255 new String[] {"org.apache.catalina.connector.Connector"});
1256 // As a side effect we'll get the container field set
1257 // Also initialize will be called
1258 //return;
1259 }
1260 // XXX Go directly to the Engine
1261 // initialize(); - is called by addConnector
1262 ObjectName engName=new ObjectName( domain + ":" + "type=Engine");
1263 if( mserver.isRegistered(engName )) {
1264 Object obj=mserver.getAttribute(engName, "managedResource");
1265 if(log.isDebugEnabled())
1266 log.debug("Found engine " + obj + " " + obj.getClass());
1267 container=(Container)obj;
1268
1269 // Internal initialize - we now have the Engine
1270 initialize();
1271
1272 if(log.isDebugEnabled())
1273 log.debug("Initialized");
1274 // As a side effect we'll get the container field set
1275 // Also initialize will be called
1276 return;
1277 }
1278 } catch( Exception ex ) {
1279 log.error( "Error finding container " + ex);
1280 }
1281 }
1282
1283 public void init() throws Exception {
1284
1285 if( this.getService() != null ) {
1286 if(log.isDebugEnabled())
1287 log.debug( "Already configured" );
1288 return;
1289 }
1290 if( container==null ) {
1291 findContainer();
1292 }
1293 }
1294
1295 public void destroy() throws Exception {
1296 if( oname!=null && controller==oname ) {
1297 if(log.isDebugEnabled())
1298 log.debug("Unregister itself " + oname );
1299 Registry.getRegistry(null, null).unregisterComponent(oname);
1300 }
1301 if( getService() == null)
1302 return;
1303 getService().removeConnector(this);
1304 }
1305
1306 }