0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.catalina.connector;
0019:
0020: import java.lang.reflect.Method;
0021: import java.net.URLEncoder;
0022: import java.util.HashMap;
0023:
0024: import javax.management.MBeanRegistration;
0025: import javax.management.MBeanServer;
0026: import javax.management.MalformedObjectNameException;
0027: import javax.management.ObjectName;
0028:
0029: import org.apache.catalina.Container;
0030: import org.apache.catalina.Lifecycle;
0031: import org.apache.catalina.LifecycleException;
0032: import org.apache.catalina.LifecycleListener;
0033: import org.apache.catalina.Service;
0034: import org.apache.catalina.core.StandardEngine;
0035: import org.apache.catalina.util.LifecycleSupport;
0036: import org.apache.catalina.util.StringManager;
0037: import org.apache.coyote.Adapter;
0038: import org.apache.coyote.ProtocolHandler;
0039: import org.apache.juli.logging.Log;
0040: import org.apache.juli.logging.LogFactory;
0041: import org.apache.tomcat.util.IntrospectionUtils;
0042: import org.apache.tomcat.util.http.mapper.Mapper;
0043: import org.apache.tomcat.util.modeler.Registry;
0044:
0045: /**
0046: * Implementation of a Coyote connector for Tomcat 5.x.
0047: *
0048: * @author Craig R. McClanahan
0049: * @author Remy Maucherat
0050: * @version $Revision: 480000 $ $Date: 2006-11-28 12:31:04 +0100 (mar., 28 nov. 2006) $
0051: */
0052:
0053: public class Connector implements Lifecycle, MBeanRegistration {
0054: private static Log log = LogFactory.getLog(Connector.class);
0055:
0056: /**
0057: * Alternate flag to enable recycling of facades.
0058: */
0059: public static final boolean RECYCLE_FACADES = Boolean.valueOf(
0060: System.getProperty(
0061: "org.apache.catalina.connector.RECYCLE_FACADES",
0062: "false")).booleanValue();
0063:
0064: // ------------------------------------------------------------ Constructor
0065:
0066: public Connector() throws Exception {
0067: this (null);
0068: }
0069:
0070: public Connector(String protocol) throws Exception {
0071: setProtocol(protocol);
0072: // Instantiate protocol handler
0073: try {
0074: Class clazz = Class.forName(protocolHandlerClassName);
0075: this .protocolHandler = (ProtocolHandler) clazz
0076: .newInstance();
0077: } catch (Exception e) {
0078: log
0079: .error(sm
0080: .getString(
0081: "coyoteConnector.protocolHandlerInstantiationFailed",
0082: e));
0083: }
0084: }
0085:
0086: // ----------------------------------------------------- Instance Variables
0087:
0088: /**
0089: * The <code>Service</code> we are associated with (if any).
0090: */
0091: protected Service service = null;
0092:
0093: /**
0094: * Do we allow TRACE ?
0095: */
0096: protected boolean allowTrace = false;
0097:
0098: /**
0099: * The Container used for processing requests received by this Connector.
0100: */
0101: protected Container container = null;
0102:
0103: /**
0104: * Use "/" as path for session cookies ?
0105: */
0106: protected boolean emptySessionPath = false;
0107:
0108: /**
0109: * The "enable DNS lookups" flag for this Connector.
0110: */
0111: protected boolean enableLookups = false;
0112:
0113: /*
0114: * Is generation of X-Powered-By response header enabled/disabled?
0115: */
0116: protected boolean xpoweredBy = false;
0117:
0118: /**
0119: * Descriptive information about this Connector implementation.
0120: */
0121: protected static final String info = "org.apache.catalina.connector.Connector/2.1";
0122:
0123: /**
0124: * The lifecycle event support for this component.
0125: */
0126: protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0127:
0128: /**
0129: * The port number on which we listen for requests.
0130: */
0131: protected int port = 0;
0132:
0133: /**
0134: * The server name to which we should pretend requests to this Connector
0135: * were directed. This is useful when operating Tomcat behind a proxy
0136: * server, so that redirects get constructed accurately. If not specified,
0137: * the server name included in the <code>Host</code> header is used.
0138: */
0139: protected String proxyName = null;
0140:
0141: /**
0142: * The server port to which we should pretent requests to this Connector
0143: * were directed. This is useful when operating Tomcat behind a proxy
0144: * server, so that redirects get constructed accurately. If not specified,
0145: * the port number specified by the <code>port</code> property is used.
0146: */
0147: protected int proxyPort = 0;
0148:
0149: /**
0150: * The redirect port for non-SSL to SSL redirects.
0151: */
0152: protected int redirectPort = 443;
0153:
0154: /**
0155: * The request scheme that will be set on all requests received
0156: * through this connector.
0157: */
0158: protected String scheme = "http";
0159:
0160: /**
0161: * The secure connection flag that will be set on all requests received
0162: * through this connector.
0163: */
0164: protected boolean secure = false;
0165:
0166: /**
0167: * The string manager for this package.
0168: */
0169: protected StringManager sm = StringManager
0170: .getManager(Constants.Package);
0171:
0172: /**
0173: * Maximum size of a POST which will be automatically parsed by the
0174: * container. 2MB by default.
0175: */
0176: protected int maxPostSize = 2 * 1024 * 1024;
0177:
0178: /**
0179: * Maximum size of a POST which will be saved by the container
0180: * during authentication. 4kB by default
0181: */
0182: protected int maxSavePostSize = 4 * 1024;
0183:
0184: /**
0185: * Has this component been initialized yet?
0186: */
0187: protected boolean initialized = false;
0188:
0189: /**
0190: * Has this component been started yet?
0191: */
0192: protected boolean started = false;
0193:
0194: /**
0195: * The shutdown signal to our background thread
0196: */
0197: protected boolean stopped = false;
0198:
0199: /**
0200: * Flag to use IP-based virtual hosting.
0201: */
0202: protected boolean useIPVHosts = false;
0203:
0204: /**
0205: * The background thread.
0206: */
0207: protected Thread thread = null;
0208:
0209: /**
0210: * Coyote Protocol handler class name.
0211: * Defaults to the Coyote HTTP/1.1 protocolHandler.
0212: */
0213: protected String protocolHandlerClassName = "org.apache.coyote.http11.Http11Protocol";
0214:
0215: /**
0216: * Coyote protocol handler.
0217: */
0218: protected ProtocolHandler protocolHandler = null;
0219:
0220: /**
0221: * Coyote adapter.
0222: */
0223: protected Adapter adapter = null;
0224:
0225: /**
0226: * Mapper.
0227: */
0228: protected Mapper mapper = new Mapper();
0229:
0230: /**
0231: * Mapper listener.
0232: */
0233: protected MapperListener mapperListener = new MapperListener(mapper);
0234:
0235: /**
0236: * URI encoding.
0237: */
0238: protected String URIEncoding = null;
0239:
0240: /**
0241: * URI encoding as body.
0242: */
0243: protected boolean useBodyEncodingForURI = false;
0244:
0245: protected static HashMap replacements = new HashMap();
0246: static {
0247: replacements.put("acceptCount", "backlog");
0248: replacements.put("connectionLinger", "soLinger");
0249: replacements.put("connectionTimeout", "soTimeout");
0250: replacements.put("connectionUploadTimeout", "timeout");
0251: replacements.put("clientAuth", "clientauth");
0252: replacements.put("keystoreFile", "keystore");
0253: replacements.put("randomFile", "randomfile");
0254: replacements.put("rootFile", "rootfile");
0255: replacements.put("keystorePass", "keypass");
0256: replacements.put("keystoreType", "keytype");
0257: replacements.put("sslProtocol", "protocol");
0258: replacements.put("sslProtocols", "protocols");
0259: }
0260:
0261: // ------------------------------------------------------------- Properties
0262:
0263: /**
0264: * Return a configured property.
0265: */
0266: public Object getProperty(String name) {
0267: String repl = name;
0268: if (replacements.get(name) != null) {
0269: repl = (String) replacements.get(name);
0270: }
0271: return IntrospectionUtils.getProperty(protocolHandler, repl);
0272: }
0273:
0274: /**
0275: * Set a configured property.
0276: */
0277: public void setProperty(String name, String value) {
0278: String repl = name;
0279: if (replacements.get(name) != null) {
0280: repl = (String) replacements.get(name);
0281: }
0282: IntrospectionUtils.setProperty(protocolHandler, repl, value);
0283: }
0284:
0285: /**
0286: * Return a configured property.
0287: */
0288: public Object getAttribute(String name) {
0289: return getProperty(name);
0290: }
0291:
0292: /**
0293: * Set a configured property.
0294: */
0295: public void setAttribute(String name, Object value) {
0296: setProperty(name, String.valueOf(value));
0297: }
0298:
0299: /**
0300: * remove a configured property.
0301: */
0302: public void removeProperty(String name) {
0303: // FIXME !
0304: //protocolHandler.removeAttribute(name);
0305: }
0306:
0307: /**
0308: * Return the <code>Service</code> with which we are associated (if any).
0309: */
0310: public Service getService() {
0311:
0312: return (this .service);
0313:
0314: }
0315:
0316: /**
0317: * Set the <code>Service</code> with which we are associated (if any).
0318: *
0319: * @param service The service that owns this Engine
0320: */
0321: public void setService(Service service) {
0322:
0323: this .service = service;
0324: // FIXME: setProperty("service", service);
0325:
0326: }
0327:
0328: /**
0329: * True if the TRACE method is allowed. Default value is "false".
0330: */
0331: public boolean getAllowTrace() {
0332:
0333: return (this .allowTrace);
0334:
0335: }
0336:
0337: /**
0338: * Set the allowTrace flag, to disable or enable the TRACE HTTP method.
0339: *
0340: * @param allowTrace The new allowTrace flag
0341: */
0342: public void setAllowTrace(boolean allowTrace) {
0343:
0344: this .allowTrace = allowTrace;
0345: setProperty("allowTrace", String.valueOf(allowTrace));
0346:
0347: }
0348:
0349: /**
0350: * Is this connector available for processing requests?
0351: */
0352: public boolean isAvailable() {
0353:
0354: return (started);
0355:
0356: }
0357:
0358: /**
0359: * Return the input buffer size for this Connector.
0360: *
0361: * @deprecated
0362: */
0363: public int getBufferSize() {
0364: return 2048;
0365: }
0366:
0367: /**
0368: * Set the input buffer size for this Connector.
0369: *
0370: * @param bufferSize The new input buffer size.
0371: * @deprecated
0372: */
0373: public void setBufferSize(int bufferSize) {
0374: }
0375:
0376: /**
0377: * Return the Container used for processing requests received by this
0378: * Connector.
0379: */
0380: public Container getContainer() {
0381: if (container == null) {
0382: // Lazy - maybe it was added later
0383: findContainer();
0384: }
0385: return (container);
0386:
0387: }
0388:
0389: /**
0390: * Set the Container used for processing requests received by this
0391: * Connector.
0392: *
0393: * @param container The new Container to use
0394: */
0395: public void setContainer(Container container) {
0396:
0397: this .container = container;
0398:
0399: }
0400:
0401: /**
0402: * Return the "empty session path" flag.
0403: */
0404: public boolean getEmptySessionPath() {
0405:
0406: return (this .emptySessionPath);
0407:
0408: }
0409:
0410: /**
0411: * Set the "empty session path" flag.
0412: *
0413: * @param emptySessionPath The new "empty session path" flag value
0414: */
0415: public void setEmptySessionPath(boolean emptySessionPath) {
0416:
0417: this .emptySessionPath = emptySessionPath;
0418: setProperty("emptySessionPath", String
0419: .valueOf(emptySessionPath));
0420:
0421: }
0422:
0423: /**
0424: * Return the "enable DNS lookups" flag.
0425: */
0426: public boolean getEnableLookups() {
0427:
0428: return (this .enableLookups);
0429:
0430: }
0431:
0432: /**
0433: * Set the "enable DNS lookups" flag.
0434: *
0435: * @param enableLookups The new "enable DNS lookups" flag value
0436: */
0437: public void setEnableLookups(boolean enableLookups) {
0438:
0439: this .enableLookups = enableLookups;
0440: setProperty("enableLookups", String.valueOf(enableLookups));
0441:
0442: }
0443:
0444: /**
0445: * Return descriptive information about this Connector implementation.
0446: */
0447: public String getInfo() {
0448:
0449: return (info);
0450:
0451: }
0452:
0453: /**
0454: * Return the mapper.
0455: */
0456: public Mapper getMapper() {
0457:
0458: return (mapper);
0459:
0460: }
0461:
0462: /**
0463: * Return the maximum size of a POST which will be automatically
0464: * parsed by the container.
0465: */
0466: public int getMaxPostSize() {
0467:
0468: return (maxPostSize);
0469:
0470: }
0471:
0472: /**
0473: * Set the maximum size of a POST which will be automatically
0474: * parsed by the container.
0475: *
0476: * @param maxPostSize The new maximum size in bytes of a POST which will
0477: * be automatically parsed by the container
0478: */
0479: public void setMaxPostSize(int maxPostSize) {
0480:
0481: this .maxPostSize = maxPostSize;
0482: }
0483:
0484: /**
0485: * Return the maximum size of a POST which will be saved by the container
0486: * during authentication.
0487: */
0488: public int getMaxSavePostSize() {
0489:
0490: return (maxSavePostSize);
0491:
0492: }
0493:
0494: /**
0495: * Set the maximum size of a POST which will be saved by the container
0496: * during authentication.
0497: *
0498: * @param maxSavePostSize The new maximum size in bytes of a POST which will
0499: * be saved by the container during authentication.
0500: */
0501: public void setMaxSavePostSize(int maxSavePostSize) {
0502:
0503: this .maxSavePostSize = maxSavePostSize;
0504: setProperty("maxSavePostSize", String.valueOf(maxSavePostSize));
0505: }
0506:
0507: /**
0508: * Return the port number on which we listen for requests.
0509: */
0510: public int getPort() {
0511:
0512: return (this .port);
0513:
0514: }
0515:
0516: /**
0517: * Set the port number on which we listen for requests.
0518: *
0519: * @param port The new port number
0520: */
0521: public void setPort(int port) {
0522:
0523: this .port = port;
0524: setProperty("port", String.valueOf(port));
0525:
0526: }
0527:
0528: /**
0529: * Return the Coyote protocol handler in use.
0530: */
0531: public String getProtocol() {
0532:
0533: if ("org.apache.coyote.http11.Http11Protocol"
0534: .equals(getProtocolHandlerClassName())
0535: || "org.apache.coyote.http11.Http11AprProtocol"
0536: .equals(getProtocolHandlerClassName())) {
0537: return "HTTP/1.1";
0538: } else if ("org.apache.jk.server.JkCoyoteHandler"
0539: .equals(getProtocolHandlerClassName())
0540: || "org.apache.coyote.ajp.AjpAprProtocol"
0541: .equals(getProtocolHandlerClassName())) {
0542: return "AJP/1.3";
0543: }
0544: return getProtocolHandlerClassName();
0545:
0546: }
0547:
0548: // ---------------------------------------------- APR Version Constants
0549:
0550: private static final int TCN_REQUIRED_MAJOR = 1;
0551: private static final int TCN_REQUIRED_MINOR = 1;
0552: private static final int TCN_REQUIRED_PATCH = 3;
0553: private static boolean aprInitialized = false;
0554:
0555: // APR init support
0556: private static synchronized void initializeAPR() {
0557: if (aprInitialized) {
0558: return;
0559: }
0560: int major = 0;
0561: int minor = 0;
0562: int patch = 0;
0563: try {
0564: String methodName = "initialize";
0565: Class paramTypes[] = new Class[1];
0566: paramTypes[0] = String.class;
0567: Object paramValues[] = new Object[1];
0568: paramValues[0] = null;
0569: Class clazz = Class
0570: .forName("org.apache.tomcat.jni.Library");
0571: Method method = clazz.getMethod(methodName, paramTypes);
0572: method.invoke(null, paramValues);
0573: major = clazz.getField("TCN_MAJOR_VERSION").getInt(null);
0574: minor = clazz.getField("TCN_MINOR_VERSION").getInt(null);
0575: patch = clazz.getField("TCN_PATCH_VERSION").getInt(null);
0576: } catch (Throwable t) {
0577: return;
0578: }
0579: if ((major != TCN_REQUIRED_MAJOR)
0580: || (minor != TCN_REQUIRED_MINOR)
0581: || (patch < TCN_REQUIRED_PATCH)) {
0582: try {
0583: // Terminate the APR in case the version
0584: // is below required.
0585: String methodName = "terminate";
0586: Method method = Class.forName(
0587: "org.apache.tomcat.jni.Library").getMethod(
0588: methodName, (Class[]) null);
0589: method.invoke(null, (Object[]) null);
0590: } catch (Throwable t) {
0591: // Ignore
0592: }
0593: return;
0594: }
0595: aprInitialized = true;
0596: }
0597:
0598: /**
0599: * Set the Coyote protocol which will be used by the connector.
0600: *
0601: * @param protocol The Coyote protocol name
0602: */
0603: public void setProtocol(String protocol) {
0604:
0605: // Test APR support
0606: initializeAPR();
0607:
0608: if (aprInitialized) {
0609: if ("HTTP/1.1".equals(protocol)) {
0610: setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol");
0611: } else if ("AJP/1.3".equals(protocol)) {
0612: setProtocolHandlerClassName("org.apache.coyote.ajp.AjpAprProtocol");
0613: } else if (protocol != null) {
0614: setProtocolHandlerClassName(protocol);
0615: } else {
0616: setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol");
0617: }
0618: } else {
0619: if ("HTTP/1.1".equals(protocol)) {
0620: setProtocolHandlerClassName("org.apache.coyote.http11.Http11Protocol");
0621: } else if ("AJP/1.3".equals(protocol)) {
0622: setProtocolHandlerClassName("org.apache.jk.server.JkCoyoteHandler");
0623: } else if (protocol != null) {
0624: setProtocolHandlerClassName(protocol);
0625: }
0626: }
0627:
0628: }
0629:
0630: /**
0631: * Return the class name of the Coyote protocol handler in use.
0632: */
0633: public String getProtocolHandlerClassName() {
0634:
0635: return (this .protocolHandlerClassName);
0636:
0637: }
0638:
0639: /**
0640: * Set the class name of the Coyote protocol handler which will be used
0641: * by the connector.
0642: *
0643: * @param protocolHandlerClassName The new class name
0644: */
0645: public void setProtocolHandlerClassName(
0646: String protocolHandlerClassName) {
0647:
0648: this .protocolHandlerClassName = protocolHandlerClassName;
0649:
0650: }
0651:
0652: /**
0653: * Return the protocol handler associated with the connector.
0654: */
0655: public ProtocolHandler getProtocolHandler() {
0656:
0657: return (this .protocolHandler);
0658:
0659: }
0660:
0661: /**
0662: * Return the proxy server name for this Connector.
0663: */
0664: public String getProxyName() {
0665:
0666: return (this .proxyName);
0667:
0668: }
0669:
0670: /**
0671: * Set the proxy server name for this Connector.
0672: *
0673: * @param proxyName The new proxy server name
0674: */
0675: public void setProxyName(String proxyName) {
0676:
0677: if (proxyName != null && proxyName.length() > 0) {
0678: this .proxyName = proxyName;
0679: setProperty("proxyName", proxyName);
0680: } else {
0681: this .proxyName = null;
0682: removeProperty("proxyName");
0683: }
0684:
0685: }
0686:
0687: /**
0688: * Return the proxy server port for this Connector.
0689: */
0690: public int getProxyPort() {
0691:
0692: return (this .proxyPort);
0693:
0694: }
0695:
0696: /**
0697: * Set the proxy server port for this Connector.
0698: *
0699: * @param proxyPort The new proxy server port
0700: */
0701: public void setProxyPort(int proxyPort) {
0702:
0703: this .proxyPort = proxyPort;
0704: setProperty("proxyPort", String.valueOf(proxyPort));
0705:
0706: }
0707:
0708: /**
0709: * Return the port number to which a request should be redirected if
0710: * it comes in on a non-SSL port and is subject to a security constraint
0711: * with a transport guarantee that requires SSL.
0712: */
0713: public int getRedirectPort() {
0714:
0715: return (this .redirectPort);
0716:
0717: }
0718:
0719: /**
0720: * Set the redirect port number.
0721: *
0722: * @param redirectPort The redirect port number (non-SSL to SSL)
0723: */
0724: public void setRedirectPort(int redirectPort) {
0725:
0726: this .redirectPort = redirectPort;
0727: setProperty("redirectPort", String.valueOf(redirectPort));
0728:
0729: }
0730:
0731: /**
0732: * Return the scheme that will be assigned to requests received
0733: * through this connector. Default value is "http".
0734: */
0735: public String getScheme() {
0736:
0737: return (this .scheme);
0738:
0739: }
0740:
0741: /**
0742: * Set the scheme that will be assigned to requests received through
0743: * this connector.
0744: *
0745: * @param scheme The new scheme
0746: */
0747: public void setScheme(String scheme) {
0748:
0749: this .scheme = scheme;
0750:
0751: }
0752:
0753: /**
0754: * Return the secure connection flag that will be assigned to requests
0755: * received through this connector. Default value is "false".
0756: */
0757: public boolean getSecure() {
0758:
0759: return (this .secure);
0760:
0761: }
0762:
0763: /**
0764: * Set the secure connection flag that will be assigned to requests
0765: * received through this connector.
0766: *
0767: * @param secure The new secure connection flag
0768: */
0769: public void setSecure(boolean secure) {
0770:
0771: this .secure = secure;
0772: setProperty("secure", Boolean.toString(secure));
0773: }
0774:
0775: /**
0776: * Return the character encoding to be used for the URI.
0777: */
0778: public String getURIEncoding() {
0779:
0780: return (this .URIEncoding);
0781:
0782: }
0783:
0784: /**
0785: * Set the URI encoding to be used for the URI.
0786: *
0787: * @param URIEncoding The new URI character encoding.
0788: */
0789: public void setURIEncoding(String URIEncoding) {
0790:
0791: this .URIEncoding = URIEncoding;
0792: setProperty("uRIEncoding", URIEncoding);
0793:
0794: }
0795:
0796: /**
0797: * Return the true if the entity body encoding should be used for the URI.
0798: */
0799: public boolean getUseBodyEncodingForURI() {
0800:
0801: return (this .useBodyEncodingForURI);
0802:
0803: }
0804:
0805: /**
0806: * Set if the entity body encoding should be used for the URI.
0807: *
0808: * @param useBodyEncodingForURI The new value for the flag.
0809: */
0810: public void setUseBodyEncodingForURI(boolean useBodyEncodingForURI) {
0811:
0812: this .useBodyEncodingForURI = useBodyEncodingForURI;
0813: setProperty("useBodyEncodingForURI", String
0814: .valueOf(useBodyEncodingForURI));
0815:
0816: }
0817:
0818: /**
0819: * Indicates whether the generation of an X-Powered-By response header for
0820: * servlet-generated responses is enabled or disabled for this Connector.
0821: *
0822: * @return true if generation of X-Powered-By response header is enabled,
0823: * false otherwise
0824: */
0825: public boolean getXpoweredBy() {
0826: return xpoweredBy;
0827: }
0828:
0829: /**
0830: * Enables or disables the generation of an X-Powered-By header (with value
0831: * Servlet/2.4) for all servlet-generated responses returned by this
0832: * Connector.
0833: *
0834: * @param xpoweredBy true if generation of X-Powered-By response header is
0835: * to be enabled, false otherwise
0836: */
0837: public void setXpoweredBy(boolean xpoweredBy) {
0838: this .xpoweredBy = xpoweredBy;
0839: setProperty("xpoweredBy", String.valueOf(xpoweredBy));
0840: }
0841:
0842: /**
0843: * Enable the use of IP-based virtual hosting.
0844: *
0845: * @param useIPVHosts <code>true</code> if Hosts are identified by IP,
0846: * <code>false/code> if Hosts are identified by name.
0847: */
0848: public void setUseIPVHosts(boolean useIPVHosts) {
0849: this .useIPVHosts = useIPVHosts;
0850: setProperty("useIPVHosts", String.valueOf(useIPVHosts));
0851: }
0852:
0853: /**
0854: * Test if IP-based virtual hosting is enabled.
0855: */
0856: public boolean getUseIPVHosts() {
0857: return useIPVHosts;
0858: }
0859:
0860: // --------------------------------------------------------- Public Methods
0861:
0862: /**
0863: * Create (or allocate) and return a Request object suitable for
0864: * specifying the contents of a Request to the responsible Container.
0865: */
0866: public Request createRequest() {
0867:
0868: Request request = new Request();
0869: request.setConnector(this );
0870: return (request);
0871:
0872: }
0873:
0874: /**
0875: * Create (or allocate) and return a Response object suitable for
0876: * receiving the contents of a Response from the responsible Container.
0877: */
0878: public Response createResponse() {
0879:
0880: Response response = new Response();
0881: response.setConnector(this );
0882: return (response);
0883:
0884: }
0885:
0886: // ------------------------------------------------------ Lifecycle Methods
0887:
0888: /**
0889: * Add a lifecycle event listener to this component.
0890: *
0891: * @param listener The listener to add
0892: */
0893: public void addLifecycleListener(LifecycleListener listener) {
0894:
0895: lifecycle.addLifecycleListener(listener);
0896:
0897: }
0898:
0899: /**
0900: * Get the lifecycle listeners associated with this lifecycle. If this
0901: * Lifecycle has no listeners registered, a zero-length array is returned.
0902: */
0903: public LifecycleListener[] findLifecycleListeners() {
0904:
0905: return lifecycle.findLifecycleListeners();
0906:
0907: }
0908:
0909: /**
0910: * Remove a lifecycle event listener from this component.
0911: *
0912: * @param listener The listener to add
0913: */
0914: public void removeLifecycleListener(LifecycleListener listener) {
0915:
0916: lifecycle.removeLifecycleListener(listener);
0917:
0918: }
0919:
0920: protected ObjectName createObjectName(String domain, String type)
0921: throws MalformedObjectNameException {
0922: String encodedAddr = null;
0923: if (getProperty("address") != null) {
0924: encodedAddr = URLEncoder.encode(getProperty("address")
0925: .toString());
0926: }
0927: String addSuffix = (getProperty("address") == null) ? ""
0928: : ",address=" + encodedAddr;
0929: ObjectName _oname = new ObjectName(domain + ":type=" + type
0930: + ",port=" + getPort() + addSuffix);
0931: return _oname;
0932: }
0933:
0934: /**
0935: * Initialize this connector (create ServerSocket here!)
0936: */
0937: public void initialize() throws LifecycleException {
0938: if (initialized) {
0939: if (log.isInfoEnabled())
0940: log
0941: .info(sm
0942: .getString("coyoteConnector.alreadyInitialized"));
0943: return;
0944: }
0945:
0946: this .initialized = true;
0947:
0948: if (oname == null && (container instanceof StandardEngine)) {
0949: try {
0950: // we are loaded directly, via API - and no name was given to us
0951: StandardEngine cb = (StandardEngine) container;
0952: oname = createObjectName(cb.getName(), "Connector");
0953: Registry.getRegistry(null, null).registerComponent(
0954: this , oname, null);
0955: controller = oname;
0956: } catch (Exception e) {
0957: log.error("Error registering connector ", e);
0958: }
0959: if (log.isDebugEnabled())
0960: log.debug("Creating name for connector " + oname);
0961: }
0962:
0963: // Initializa adapter
0964: adapter = new CoyoteAdapter(this );
0965: protocolHandler.setAdapter(adapter);
0966:
0967: IntrospectionUtils.setProperty(protocolHandler, "jkHome",
0968: System.getProperty("catalina.base"));
0969:
0970: try {
0971: protocolHandler.init();
0972: } catch (Exception e) {
0973: throw new LifecycleException(
0974: sm
0975: .getString(
0976: "coyoteConnector.protocolHandlerInitializationFailed",
0977: e));
0978: }
0979: }
0980:
0981: /**
0982: * Pause the connector.
0983: */
0984: public void pause() throws LifecycleException {
0985: try {
0986: protocolHandler.pause();
0987: } catch (Exception e) {
0988: log
0989: .error(
0990: sm
0991: .getString("coyoteConnector.protocolHandlerPauseFailed"),
0992: e);
0993: }
0994: }
0995:
0996: /**
0997: * Pause the connector.
0998: */
0999: public void resume() throws LifecycleException {
1000: try {
1001: protocolHandler.resume();
1002: } catch (Exception e) {
1003: log
1004: .error(
1005: sm
1006: .getString("coyoteConnector.protocolHandlerResumeFailed"),
1007: e);
1008: }
1009: }
1010:
1011: /**
1012: * Begin processing requests via this Connector.
1013: *
1014: * @exception LifecycleException if a fatal startup error occurs
1015: */
1016: public void start() throws LifecycleException {
1017: if (!initialized)
1018: initialize();
1019:
1020: // Validate and update our current state
1021: if (started) {
1022: if (log.isInfoEnabled())
1023: log
1024: .info(sm
1025: .getString("coyoteConnector.alreadyStarted"));
1026: return;
1027: }
1028: lifecycle.fireLifecycleEvent(START_EVENT, null);
1029: started = true;
1030:
1031: // We can't register earlier - the JMX registration of this happens
1032: // in Server.start callback
1033: if (this .oname != null) {
1034: // We are registred - register the adapter as well.
1035: try {
1036: Registry.getRegistry(null, null)
1037: .registerComponent(
1038: protocolHandler,
1039: createObjectName(this .domain,
1040: "ProtocolHandler"), null);
1041: } catch (Exception ex) {
1042: log
1043: .error(
1044: sm
1045: .getString("coyoteConnector.protocolRegistrationFailed"),
1046: ex);
1047: }
1048: } else {
1049: if (log.isInfoEnabled())
1050: log
1051: .info(sm
1052: .getString("coyoteConnector.cannotRegisterProtocol"));
1053: }
1054:
1055: try {
1056: protocolHandler.start();
1057: } catch (Exception e) {
1058: String errPrefix = "";
1059: if (this .service != null) {
1060: errPrefix += "service.getName(): \""
1061: + this .service.getName() + "\"; ";
1062: }
1063:
1064: throw new LifecycleException(
1065: errPrefix
1066: + " "
1067: + sm
1068: .getString(
1069: "coyoteConnector.protocolHandlerStartFailed",
1070: e));
1071: }
1072:
1073: if (this .domain != null) {
1074: mapperListener.setDomain(domain);
1075: //mapperListener.setEngine( service.getContainer().getName() );
1076: mapperListener.init();
1077: try {
1078: ObjectName mapperOname = createObjectName(this .domain,
1079: "Mapper");
1080: if (log.isDebugEnabled())
1081: log.debug(sm.getString(
1082: "coyoteConnector.MapperRegistration",
1083: mapperOname));
1084: Registry.getRegistry(null, null).registerComponent(
1085: mapper, mapperOname, "Mapper");
1086: } catch (Exception ex) {
1087: log
1088: .error(
1089: sm
1090: .getString("coyoteConnector.protocolRegistrationFailed"),
1091: ex);
1092: }
1093: }
1094: }
1095:
1096: /**
1097: * Terminate processing requests via this Connector.
1098: *
1099: * @exception LifecycleException if a fatal shutdown error occurs
1100: */
1101: public void stop() throws LifecycleException {
1102:
1103: // Validate and update our current state
1104: if (!started) {
1105: log.error(sm.getString("coyoteConnector.notStarted"));
1106: return;
1107:
1108: }
1109: lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1110: started = false;
1111:
1112: try {
1113: mapperListener.destroy();
1114: Registry.getRegistry(null, null).unregisterComponent(
1115: createObjectName(this .domain, "Mapper"));
1116: Registry.getRegistry(null, null).unregisterComponent(
1117: createObjectName(this .domain, "ProtocolHandler"));
1118: } catch (MalformedObjectNameException e) {
1119: log
1120: .error(
1121: sm
1122: .getString("coyoteConnector.protocolUnregistrationFailed"),
1123: e);
1124: }
1125: try {
1126: protocolHandler.destroy();
1127: } catch (Exception e) {
1128: throw new LifecycleException(sm.getString(
1129: "coyoteConnector.protocolHandlerDestroyFailed", e));
1130: }
1131:
1132: }
1133:
1134: // -------------------- JMX registration --------------------
1135: protected String domain;
1136: protected ObjectName oname;
1137: protected MBeanServer mserver;
1138: ObjectName controller;
1139:
1140: public ObjectName getController() {
1141: return controller;
1142: }
1143:
1144: public void setController(ObjectName controller) {
1145: this .controller = controller;
1146: }
1147:
1148: public ObjectName getObjectName() {
1149: return oname;
1150: }
1151:
1152: public String getDomain() {
1153: return domain;
1154: }
1155:
1156: public ObjectName preRegister(MBeanServer server, ObjectName name)
1157: throws Exception {
1158: oname = name;
1159: mserver = server;
1160: domain = name.getDomain();
1161: return name;
1162: }
1163:
1164: public void postRegister(Boolean registrationDone) {
1165: }
1166:
1167: public void preDeregister() throws Exception {
1168: }
1169:
1170: public void postDeregister() {
1171: try {
1172: if (started) {
1173: stop();
1174: }
1175: } catch (Throwable t) {
1176: log.error("Unregistering - can't stop", t);
1177: }
1178: }
1179:
1180: protected void findContainer() {
1181: try {
1182: // Register to the service
1183: ObjectName parentName = new ObjectName(domain + ":"
1184: + "type=Service");
1185:
1186: if (log.isDebugEnabled())
1187: log.debug("Adding to " + parentName);
1188: if (mserver.isRegistered(parentName)) {
1189: mserver
1190: .invoke(
1191: parentName,
1192: "addConnector",
1193: new Object[] { this },
1194: new String[] { "org.apache.catalina.connector.Connector" });
1195: // As a side effect we'll get the container field set
1196: // Also initialize will be called
1197: //return;
1198: }
1199: // XXX Go directly to the Engine
1200: // initialize(); - is called by addConnector
1201: ObjectName engName = new ObjectName(domain + ":"
1202: + "type=Engine");
1203: if (mserver.isRegistered(engName)) {
1204: Object obj = mserver.getAttribute(engName,
1205: "managedResource");
1206: if (log.isDebugEnabled())
1207: log.debug("Found engine " + obj + " "
1208: + obj.getClass());
1209: container = (Container) obj;
1210:
1211: // Internal initialize - we now have the Engine
1212: initialize();
1213:
1214: if (log.isDebugEnabled())
1215: log.debug("Initialized");
1216: // As a side effect we'll get the container field set
1217: // Also initialize will be called
1218: return;
1219: }
1220: } catch (Exception ex) {
1221: log.error("Error finding container " + ex);
1222: }
1223: }
1224:
1225: public void init() throws Exception {
1226:
1227: if (this .getService() != null) {
1228: if (log.isDebugEnabled())
1229: log.debug("Already configured");
1230: return;
1231: }
1232: if (container == null) {
1233: findContainer();
1234: }
1235: }
1236:
1237: public void destroy() throws Exception {
1238: if (oname != null && controller == oname) {
1239: if (log.isDebugEnabled())
1240: log.debug("Unregister itself " + oname);
1241: Registry.getRegistry(null, null).unregisterComponent(oname);
1242: }
1243: if (getService() == null)
1244: return;
1245: getService().removeConnector(this);
1246: }
1247:
1248: }
|