-/*\r
- * Copyright 1999,2004-2005 The Apache Software Foundation.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-\r
-package org.apache.catalina.connector;\r
-\r
-import java.lang.reflect.Method;\r
-import java.net.URLEncoder;\r
-import java.util.HashMap;\r
-\r
-import javax.management.MBeanRegistration;\r
-import javax.management.MBeanServer;\r
-import javax.management.MalformedObjectNameException;\r
-import javax.management.ObjectName;\r
-\r
-import org.apache.catalina.Container;\r
-import org.apache.catalina.Lifecycle;\r
-import org.apache.catalina.LifecycleException;\r
-import org.apache.catalina.LifecycleListener;\r
-import org.apache.catalina.Service;\r
-import org.apache.catalina.core.StandardEngine;\r
-import org.apache.catalina.util.LifecycleSupport;\r
-import org.apache.catalina.util.StringManager;\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.apache.coyote.Adapter;\r
-import org.apache.coyote.ProtocolHandler;\r
-import org.apache.tomcat.util.IntrospectionUtils;\r
-import org.apache.tomcat.util.http.mapper.Mapper;\r
-import org.apache.tomcat.util.modeler.Registry;\r
-\r
-\r
-/**\r
- * Implementation of a Coyote connector for Tomcat 5.x.\r
- *\r
- * @author Craig R. McClanahan\r
- * @author Remy Maucherat\r
- * @version $Revision: 349505 $ $Date: 2005-11-28 22:14:21 +0100 (lun., 28 nov. 2005) $\r
- */\r
-\r
-\r
-public class Connector\r
- implements Lifecycle, MBeanRegistration\r
-{\r
- private static Log log = LogFactory.getLog(Connector.class);\r
-\r
-\r
- // ------------------------------------------------------------ Constructor\r
-\r
-\r
- public Connector()\r
- throws Exception {\r
- this(null);\r
- }\r
- \r
- public Connector(String protocol) \r
- throws Exception {\r
- setProtocol(protocol);\r
- // Instantiate protocol handler\r
- try {\r
- Class clazz = Class.forName(protocolHandlerClassName);\r
- this.protocolHandler = (ProtocolHandler) clazz.newInstance();\r
- } catch (Exception e) {\r
- log.error\r
- (sm.getString\r
- ("coyoteConnector.protocolHandlerInstantiationFailed", e));\r
- }\r
- }\r
- \r
- \r
- // ----------------------------------------------------- Instance Variables\r
-\r
-\r
- /**\r
- * The <code>Service</code> we are associated with (if any).\r
- */\r
- protected Service service = null;\r
-\r
-\r
- /**\r
- * Do we allow TRACE ?\r
- */\r
- protected boolean allowTrace = false;\r
-\r
-\r
- /**\r
- * The Container used for processing requests received by this Connector.\r
- */\r
- protected Container container = null;\r
-\r
-\r
- /**\r
- * Use "/" as path for session cookies ?\r
- */\r
- protected boolean emptySessionPath = false;\r
-\r
-\r
- /**\r
- * The "enable DNS lookups" flag for this Connector.\r
- */\r
- protected boolean enableLookups = false;\r
-\r
-\r
- /*\r
- * Is generation of X-Powered-By response header enabled/disabled?\r
- */\r
- protected boolean xpoweredBy = false;\r
-\r
-\r
- /**\r
- * Descriptive information about this Connector implementation.\r
- */\r
- protected static final String info =\r
- "org.apache.catalina.connector.Connector/2.1";\r
-\r
-\r
- /**\r
- * The lifecycle event support for this component.\r
- */\r
- protected LifecycleSupport lifecycle = new LifecycleSupport(this);\r
-\r
-\r
- /**\r
- * The port number on which we listen for requests.\r
- */\r
- protected int port = 0;\r
-\r
-\r
- /**\r
- * The server name to which we should pretend requests to this Connector\r
- * were directed. This is useful when operating Tomcat behind a proxy\r
- * server, so that redirects get constructed accurately. If not specified,\r
- * the server name included in the <code>Host</code> header is used.\r
- */\r
- protected String proxyName = null;\r
-\r
-\r
- /**\r
- * The server port to which we should pretent requests to this Connector\r
- * were directed. This is useful when operating Tomcat behind a proxy\r
- * server, so that redirects get constructed accurately. If not specified,\r
- * the port number specified by the <code>port</code> property is used.\r
- */\r
- protected int proxyPort = 0;\r
-\r
-\r
- /**\r
- * The redirect port for non-SSL to SSL redirects.\r
- */\r
- protected int redirectPort = 443;\r
-\r
-\r
- /**\r
- * The request scheme that will be set on all requests received\r
- * through this connector.\r
- */\r
- protected String scheme = "http";\r
-\r
-\r
- /**\r
- * The secure connection flag that will be set on all requests received\r
- * through this connector.\r
- */\r
- protected boolean secure = false;\r
-\r
-\r
- /**\r
- * The string manager for this package.\r
- */\r
- protected StringManager sm =\r
- StringManager.getManager(Constants.Package);\r
-\r
-\r
- /**\r
- * Maximum size of a POST which will be automatically parsed by the \r
- * container. 2MB by default.\r
- */\r
- protected int maxPostSize = 2 * 1024 * 1024;\r
-\r
-\r
- /**\r
- * Maximum size of a POST which will be saved by the container\r
- * during authentication. 4kB by default\r
- */\r
- protected int maxSavePostSize = 4 * 1024;\r
-\r
-\r
- /**\r
- * Has this component been initialized yet?\r
- */\r
- protected boolean initialized = false;\r
-\r
-\r
- /**\r
- * Has this component been started yet?\r
- */\r
- protected boolean started = false;\r
-\r
-\r
- /**\r
- * The shutdown signal to our background thread\r
- */\r
- protected boolean stopped = false;\r
-\r
- /**\r
- * Flag to use IP-based virtual hosting.\r
- */\r
- protected boolean useIPVHosts = false;\r
-\r
- /**\r
- * The background thread.\r
- */\r
- protected Thread thread = null;\r
-\r
-\r
- /**\r
- * Coyote Protocol handler class name.\r
- * Defaults to the Coyote HTTP/1.1 protocolHandler.\r
- */\r
- protected String protocolHandlerClassName =\r
- "org.apache.coyote.http11.Http11Protocol";\r
-\r
-\r
- /**\r
- * Coyote protocol handler.\r
- */\r
- protected ProtocolHandler protocolHandler = null;\r
-\r
-\r
- /**\r
- * Coyote adapter.\r
- */\r
- protected Adapter adapter = null;\r
-\r
-\r
- /**\r
- * Mapper.\r
- */\r
- protected Mapper mapper = new Mapper();\r
-\r
-\r
- /**\r
- * Mapper listener.\r
- */\r
- protected MapperListener mapperListener = new MapperListener(mapper);\r
-\r
-\r
- /**\r
- * URI encoding.\r
- */\r
- protected String URIEncoding = null;\r
-\r
-\r
- /**\r
- * URI encoding as body.\r
- */\r
- protected boolean useBodyEncodingForURI = false;\r
-\r
-\r
- protected static HashMap replacements = new HashMap();\r
- static {\r
- replacements.put("acceptCount", "backlog");\r
- replacements.put("connectionLinger", "soLinger");\r
- replacements.put("connectionTimeout", "soTimeout");\r
- replacements.put("connectionUploadTimeout", "timeout");\r
- replacements.put("clientAuth", "clientauth");\r
- replacements.put("keystoreFile", "keystore");\r
- replacements.put("randomFile", "randomfile");\r
- replacements.put("rootFile", "rootfile");\r
- replacements.put("keystorePass", "keypass");\r
- replacements.put("keystoreType", "keytype");\r
- replacements.put("sslProtocol", "protocol");\r
- replacements.put("sslProtocols", "protocols");\r
- }\r
- \r
- \r
- // ------------------------------------------------------------- Properties\r
-\r
-\r
- /**\r
- * Return a configured property.\r
- */\r
- public Object getProperty(String name) {\r
- String repl = name;\r
- if (replacements.get(name) != null) {\r
- repl = (String) replacements.get(name);\r
- }\r
- return IntrospectionUtils.getProperty(protocolHandler, repl);\r
- }\r
-\r
- \r
- /**\r
- * Set a configured property.\r
- */\r
- public void setProperty(String name, String value) {\r
- String repl = name;\r
- if (replacements.get(name) != null) {\r
- repl = (String) replacements.get(name);\r
- }\r
- IntrospectionUtils.setProperty(protocolHandler, repl, value);\r
- }\r
-\r
- \r
- /**\r
- * Return a configured property.\r
- */\r
- public Object getAttribute(String name) {\r
- return getProperty(name);\r
- }\r
-\r
- \r
- /**\r
- * Set a configured property.\r
- */\r
- public void setAttribute(String name, Object value) {\r
- setProperty(name, String.valueOf(value));\r
- }\r
-\r
- \r
- /** \r
- * remove a configured property.\r
- */\r
- public void removeProperty(String name) {\r
- // FIXME !\r
- //protocolHandler.removeAttribute(name);\r
- }\r
-\r
- \r
- /**\r
- * Return the <code>Service</code> with which we are associated (if any).\r
- */\r
- public Service getService() {\r
-\r
- return (this.service);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the <code>Service</code> with which we are associated (if any).\r
- *\r
- * @param service The service that owns this Engine\r
- */\r
- public void setService(Service service) {\r
-\r
- this.service = service;\r
- // FIXME: setProperty("service", service);\r
-\r
- }\r
-\r
-\r
- /**\r
- * True if the TRACE method is allowed. Default value is "false".\r
- */\r
- public boolean getAllowTrace() {\r
-\r
- return (this.allowTrace);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the allowTrace flag, to disable or enable the TRACE HTTP method.\r
- *\r
- * @param allowTrace The new allowTrace flag\r
- */\r
- public void setAllowTrace(boolean allowTrace) {\r
-\r
- this.allowTrace = allowTrace;\r
- setProperty("allowTrace", String.valueOf(allowTrace));\r
-\r
- }\r
-\r
- /**\r
- * Is this connector available for processing requests?\r
- */\r
- public boolean isAvailable() {\r
-\r
- return (started);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the input buffer size for this Connector.\r
- * \r
- * @deprecated\r
- */\r
- public int getBufferSize() {\r
- return 2048;\r
- }\r
-\r
- /**\r
- * Set the input buffer size for this Connector.\r
- *\r
- * @param bufferSize The new input buffer size.\r
- * @deprecated\r
- */\r
- public void setBufferSize(int bufferSize) {\r
- }\r
-\r
- \r
- /**\r
- * Return the Container used for processing requests received by this\r
- * Connector.\r
- */\r
- public Container getContainer() {\r
- if( container==null ) {\r
- // Lazy - maybe it was added later\r
- findContainer(); \r
- }\r
- return (container);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the Container used for processing requests received by this\r
- * Connector.\r
- *\r
- * @param container The new Container to use\r
- */\r
- public void setContainer(Container container) {\r
-\r
- this.container = container;\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the "empty session path" flag.\r
- */\r
- public boolean getEmptySessionPath() {\r
-\r
- return (this.emptySessionPath);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the "empty session path" flag.\r
- *\r
- * @param emptySessionPath The new "empty session path" flag value\r
- */\r
- public void setEmptySessionPath(boolean emptySessionPath) {\r
-\r
- this.emptySessionPath = emptySessionPath;\r
- setProperty("emptySessionPath", String.valueOf(emptySessionPath));\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the "enable DNS lookups" flag.\r
- */\r
- public boolean getEnableLookups() {\r
-\r
- return (this.enableLookups);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the "enable DNS lookups" flag.\r
- *\r
- * @param enableLookups The new "enable DNS lookups" flag value\r
- */\r
- public void setEnableLookups(boolean enableLookups) {\r
-\r
- this.enableLookups = enableLookups;\r
- setProperty("enableLookups", String.valueOf(enableLookups));\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return descriptive information about this Connector implementation.\r
- */\r
- public String getInfo() {\r
-\r
- return (info);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the mapper.\r
- */\r
- public Mapper getMapper() {\r
-\r
- return (mapper);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the maximum size of a POST which will be automatically\r
- * parsed by the container.\r
- */\r
- public int getMaxPostSize() {\r
-\r
- return (maxPostSize);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the maximum size of a POST which will be automatically\r
- * parsed by the container.\r
- *\r
- * @param maxPostSize The new maximum size in bytes of a POST which will \r
- * be automatically parsed by the container\r
- */\r
- public void setMaxPostSize(int maxPostSize) {\r
-\r
- this.maxPostSize = maxPostSize;\r
- }\r
-\r
-\r
- /**\r
- * Return the maximum size of a POST which will be saved by the container\r
- * during authentication.\r
- */\r
- public int getMaxSavePostSize() {\r
-\r
- return (maxSavePostSize);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the maximum size of a POST which will be saved by the container\r
- * during authentication.\r
- *\r
- * @param maxSavePostSize The new maximum size in bytes of a POST which will\r
- * be saved by the container during authentication.\r
- */\r
- public void setMaxSavePostSize(int maxSavePostSize) {\r
-\r
- this.maxSavePostSize = maxSavePostSize;\r
- setProperty("maxSavePostSize", String.valueOf(maxSavePostSize));\r
- }\r
-\r
-\r
- /**\r
- * Return the port number on which we listen for requests.\r
- */\r
- public int getPort() {\r
-\r
- return (this.port);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the port number on which we listen for requests.\r
- *\r
- * @param port The new port number\r
- */\r
- public void setPort(int port) {\r
-\r
- this.port = port;\r
- setProperty("port", String.valueOf(port));\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the Coyote protocol handler in use.\r
- */\r
- public String getProtocol() {\r
-\r
- if ("org.apache.coyote.http11.Http11Protocol".equals\r
- (getProtocolHandlerClassName())\r
- || "org.apache.coyote.http11.Http11AprProtocol".equals\r
- (getProtocolHandlerClassName())) {\r
- return "HTTP/1.1";\r
- } else if ("org.apache.jk.server.JkCoyoteHandler".equals\r
- (getProtocolHandlerClassName())\r
- || "org.apache.coyote.ajp.AjpAprProtocol".equals\r
- (getProtocolHandlerClassName())) {\r
- return "AJP/1.3";\r
- }\r
- return getProtocolHandlerClassName();\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the Coyote protocol which will be used by the connector.\r
- *\r
- * @param protocol The Coyote protocol name\r
- */\r
- public void setProtocol(String protocol) {\r
-\r
- // Test APR support\r
- boolean apr = false;\r
- try {\r
- String methodName = "initialize";\r
- Class paramTypes[] = new Class[1];\r
- paramTypes[0] = String.class;\r
- Object paramValues[] = new Object[1];\r
- paramValues[0] = null;\r
- Method method = Class.forName("org.apache.tomcat.jni.Library")\r
- .getMethod(methodName, paramTypes);\r
- method.invoke(null, paramValues);\r
- apr = true;\r
- } catch (Throwable t) {\r
- // Ignore\r
- }\r
-\r
- if (apr) {\r
- if ("HTTP/1.1".equals(protocol)) {\r
- setProtocolHandlerClassName\r
- ("org.apache.coyote.http11.Http11AprProtocol");\r
- } else if ("AJP/1.3".equals(protocol)) {\r
- setProtocolHandlerClassName\r
- ("org.apache.coyote.ajp.AjpAprProtocol");\r
- } else if (protocol != null) {\r
- setProtocolHandlerClassName(protocol);\r
- } else {\r
- setProtocolHandlerClassName\r
- ("org.apache.coyote.http11.Http11AprProtocol");\r
- }\r
- } else {\r
- if ("HTTP/1.1".equals(protocol)) {\r
- setProtocolHandlerClassName\r
- ("org.apache.coyote.http11.Http11Protocol");\r
- } else if ("AJP/1.3".equals(protocol)) {\r
- setProtocolHandlerClassName\r
- ("org.apache.jk.server.JkCoyoteHandler");\r
- } else if (protocol != null) {\r
- setProtocolHandlerClassName(protocol);\r
- }\r
- }\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the class name of the Coyote protocol handler in use.\r
- */\r
- public String getProtocolHandlerClassName() {\r
-\r
- return (this.protocolHandlerClassName);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the class name of the Coyote protocol handler which will be used\r
- * by the connector.\r
- *\r
- * @param protocolHandlerClassName The new class name\r
- */\r
- public void setProtocolHandlerClassName(String protocolHandlerClassName) {\r
-\r
- this.protocolHandlerClassName = protocolHandlerClassName;\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the protocol handler associated with the connector.\r
- */\r
- public ProtocolHandler getProtocolHandler() {\r
-\r
- return (this.protocolHandler);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the proxy server name for this Connector.\r
- */\r
- public String getProxyName() {\r
-\r
- return (this.proxyName);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the proxy server name for this Connector.\r
- *\r
- * @param proxyName The new proxy server name\r
- */\r
- public void setProxyName(String proxyName) {\r
-\r
- if(proxyName != null && proxyName.length() > 0) {\r
- this.proxyName = proxyName;\r
- setProperty("proxyName", proxyName);\r
- } else {\r
- this.proxyName = null;\r
- removeProperty("proxyName");\r
- }\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the proxy server port for this Connector.\r
- */\r
- public int getProxyPort() {\r
-\r
- return (this.proxyPort);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the proxy server port for this Connector.\r
- *\r
- * @param proxyPort The new proxy server port\r
- */\r
- public void setProxyPort(int proxyPort) {\r
-\r
- this.proxyPort = proxyPort;\r
- setProperty("proxyPort", String.valueOf(proxyPort));\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the port number to which a request should be redirected if\r
- * it comes in on a non-SSL port and is subject to a security constraint\r
- * with a transport guarantee that requires SSL.\r
- */\r
- public int getRedirectPort() {\r
-\r
- return (this.redirectPort);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the redirect port number.\r
- *\r
- * @param redirectPort The redirect port number (non-SSL to SSL)\r
- */\r
- public void setRedirectPort(int redirectPort) {\r
-\r
- this.redirectPort = redirectPort;\r
- setProperty("redirectPort", String.valueOf(redirectPort));\r
-\r
- }\r
-\r
- \r
- /**\r
- * Return the scheme that will be assigned to requests received\r
- * through this connector. Default value is "http".\r
- */\r
- public String getScheme() {\r
-\r
- return (this.scheme);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the scheme that will be assigned to requests received through\r
- * this connector.\r
- *\r
- * @param scheme The new scheme\r
- */\r
- public void setScheme(String scheme) {\r
-\r
- this.scheme = scheme;\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the secure connection flag that will be assigned to requests\r
- * received through this connector. Default value is "false".\r
- */\r
- public boolean getSecure() {\r
-\r
- return (this.secure);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the secure connection flag that will be assigned to requests\r
- * received through this connector.\r
- *\r
- * @param secure The new secure connection flag\r
- */\r
- public void setSecure(boolean secure) {\r
-\r
- this.secure = secure;\r
- setProperty("secure", Boolean.toString(secure));\r
- }\r
-\r
- /**\r
- * Return the character encoding to be used for the URI.\r
- */\r
- public String getURIEncoding() {\r
-\r
- return (this.URIEncoding);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set the URI encoding to be used for the URI.\r
- *\r
- * @param URIEncoding The new URI character encoding.\r
- */\r
- public void setURIEncoding(String URIEncoding) {\r
-\r
- this.URIEncoding = URIEncoding;\r
- setProperty("uRIEncoding", URIEncoding);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Return the true if the entity body encoding should be used for the URI.\r
- */\r
- public boolean getUseBodyEncodingForURI() {\r
-\r
- return (this.useBodyEncodingForURI);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Set if the entity body encoding should be used for the URI.\r
- *\r
- * @param useBodyEncodingForURI The new value for the flag.\r
- */\r
- public void setUseBodyEncodingForURI(boolean useBodyEncodingForURI) {\r
-\r
- this.useBodyEncodingForURI = useBodyEncodingForURI;\r
- setProperty\r
- ("useBodyEncodingForURI", String.valueOf(useBodyEncodingForURI));\r
-\r
- }\r
-\r
-\r
- /**\r
- * Indicates whether the generation of an X-Powered-By response header for\r
- * servlet-generated responses is enabled or disabled for this Connector.\r
- *\r
- * @return true if generation of X-Powered-By response header is enabled,\r
- * false otherwise\r
- */\r
- public boolean getXpoweredBy() {\r
- return xpoweredBy;\r
- }\r
-\r
-\r
- /**\r
- * Enables or disables the generation of an X-Powered-By header (with value\r
- * Servlet/2.4) for all servlet-generated responses returned by this\r
- * Connector.\r
- *\r
- * @param xpoweredBy true if generation of X-Powered-By response header is\r
- * to be enabled, false otherwise\r
- */\r
- public void setXpoweredBy(boolean xpoweredBy) {\r
- this.xpoweredBy = xpoweredBy;\r
- setProperty("xpoweredBy", String.valueOf(xpoweredBy));\r
- }\r
-\r
- /**\r
- * Enable the use of IP-based virtual hosting.\r
- *\r
- * @param useIPVHosts <code>true</code> if Hosts are identified by IP,\r
- * <code>false/code> if Hosts are identified by name.\r
- */\r
- public void setUseIPVHosts(boolean useIPVHosts) {\r
- this.useIPVHosts = useIPVHosts;\r
- setProperty("useIPVHosts", String.valueOf(useIPVHosts));\r
- }\r
-\r
- /**\r
- * Test if IP-based virtual hosting is enabled.\r
- */\r
- public boolean getUseIPVHosts() {\r
- return useIPVHosts;\r
- }\r
-\r
- // --------------------------------------------------------- Public Methods\r
-\r
-\r
- /**\r
- * Create (or allocate) and return a Request object suitable for\r
- * specifying the contents of a Request to the responsible Container.\r
- */\r
- public Request createRequest() {\r
-\r
- Request request = new Request();\r
- request.setConnector(this);\r
- return (request);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Create (or allocate) and return a Response object suitable for\r
- * receiving the contents of a Response from the responsible Container.\r
- */\r
- public Response createResponse() {\r
-\r
- Response response = new Response();\r
- response.setConnector(this);\r
- return (response);\r
-\r
- }\r
-\r
-\r
- // ------------------------------------------------------ Lifecycle Methods\r
-\r
-\r
- /**\r
- * Add a lifecycle event listener to this component.\r
- *\r
- * @param listener The listener to add\r
- */\r
- public void addLifecycleListener(LifecycleListener listener) {\r
-\r
- lifecycle.addLifecycleListener(listener);\r
-\r
- }\r
-\r
-\r
- /**\r
- * Get the lifecycle listeners associated with this lifecycle. If this\r
- * Lifecycle has no listeners registered, a zero-length array is returned.\r
- */\r
- public LifecycleListener[] findLifecycleListeners() {\r
-\r
- return lifecycle.findLifecycleListeners();\r
-\r
- }\r
-\r
-\r
- /**\r
- * Remove a lifecycle event listener from this component.\r
- *\r
- * @param listener The listener to add\r
- */\r
- public void removeLifecycleListener(LifecycleListener listener) {\r
-\r
- lifecycle.removeLifecycleListener(listener);\r
-\r
- }\r
-\r
- \r
- protected ObjectName createObjectName(String domain, String type)\r
- throws MalformedObjectNameException {\r
- String encodedAddr = null;\r
- if (getProperty("address") != null) {\r
- encodedAddr = URLEncoder.encode(getProperty("address").toString());\r
- }\r
- String addSuffix = (getProperty("address") == null) ? "" : ",address="\r
- + encodedAddr;\r
- ObjectName _oname = new ObjectName(domain + ":type=" + type + ",port="\r
- + getPort() + addSuffix);\r
- return _oname;\r
- }\r
- \r
- /**\r
- * Initialize this connector (create ServerSocket here!)\r
- */\r
- public void initialize()\r
- throws LifecycleException\r
- {\r
- if (initialized) {\r
- if(log.isInfoEnabled())\r
- log.info(sm.getString("coyoteConnector.alreadyInitialized"));\r
- return;\r
- }\r
-\r
- this.initialized = true;\r
-\r
- if( oname == null && (container instanceof StandardEngine)) {\r
- try {\r
- // we are loaded directly, via API - and no name was given to us\r
- StandardEngine cb=(StandardEngine)container;\r
- oname = createObjectName(cb.getName(), "Connector");\r
- Registry.getRegistry(null, null)\r
- .registerComponent(this, oname, null);\r
- controller=oname;\r
- } catch (Exception e) {\r
- log.error( "Error registering connector ", e);\r
- }\r
- if(log.isDebugEnabled())\r
- log.debug("Creating name for connector " + oname);\r
- }\r
-\r
- // Initializa adapter\r
- adapter = new CoyoteAdapter(this);\r
- protocolHandler.setAdapter(adapter);\r
-\r
- IntrospectionUtils.setProperty(protocolHandler, "jkHome",\r
- System.getProperty("catalina.base"));\r
-\r
- try {\r
- protocolHandler.init();\r
- } catch (Exception e) {\r
- throw new LifecycleException\r
- (sm.getString\r
- ("coyoteConnector.protocolHandlerInitializationFailed", e));\r
- }\r
- }\r
-\r
-\r
- /**\r
- * Pause the connector.\r
- */\r
- public void pause()\r
- throws LifecycleException {\r
- try {\r
- protocolHandler.pause();\r
- } catch (Exception e) {\r
- log.error(sm.getString\r
- ("coyoteConnector.protocolHandlerPauseFailed"), e);\r
- }\r
- }\r
-\r
-\r
- /**\r
- * Pause the connector.\r
- */\r
- public void resume()\r
- throws LifecycleException {\r
- try {\r
- protocolHandler.resume();\r
- } catch (Exception e) {\r
- log.error(sm.getString\r
- ("coyoteConnector.protocolHandlerResumeFailed"), e);\r
- }\r
- }\r
-\r
-\r
- /**\r
- * Begin processing requests via this Connector.\r
- *\r
- * @exception LifecycleException if a fatal startup error occurs\r
- */\r
- public void start() throws LifecycleException {\r
- if( !initialized )\r
- initialize();\r
-\r
- // Validate and update our current state\r
- if (started ) {\r
- if(log.isInfoEnabled())\r
- log.info(sm.getString("coyoteConnector.alreadyStarted"));\r
- return;\r
- }\r
- lifecycle.fireLifecycleEvent(START_EVENT, null);\r
- started = true;\r
-\r
- // We can't register earlier - the JMX registration of this happens\r
- // in Server.start callback\r
- if ( this.oname != null ) {\r
- // We are registred - register the adapter as well.\r
- try {\r
- Registry.getRegistry(null, null).registerComponent\r
- (protocolHandler, createObjectName(this.domain,"ProtocolHandler"), null);\r
- } catch (Exception ex) {\r
- log.error(sm.getString\r
- ("coyoteConnector.protocolRegistrationFailed"), ex);\r
- }\r
- } else {\r
- if(log.isInfoEnabled())\r
- log.info(sm.getString\r
- ("coyoteConnector.cannotRegisterProtocol"));\r
- }\r
-\r
- try {\r
- protocolHandler.start();\r
- } catch (Exception e) {\r
- String errPrefix = "";\r
- if(this.service != null) {\r
- errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";\r
- }\r
-\r
- throw new LifecycleException\r
- (errPrefix + " " + sm.getString\r
- ("coyoteConnector.protocolHandlerStartFailed", e));\r
- }\r
-\r
- if( this.domain != null ) {\r
- mapperListener.setDomain( domain );\r
- //mapperListener.setEngine( service.getContainer().getName() );\r
- mapperListener.init();\r
- try {\r
- ObjectName mapperOname = createObjectName(this.domain,"Mapper");\r
- if (log.isDebugEnabled())\r
- log.debug(sm.getString(\r
- "coyoteConnector.MapperRegistration", mapperOname));\r
- Registry.getRegistry(null, null).registerComponent\r
- (mapper, mapperOname, "Mapper");\r
- } catch (Exception ex) {\r
- log.error(sm.getString\r
- ("coyoteConnector.protocolRegistrationFailed"), ex);\r
- }\r
- }\r
- }\r
-\r
-\r
- /**\r
- * Terminate processing requests via this Connector.\r
- *\r
- * @exception LifecycleException if a fatal shutdown error occurs\r
- */\r
- public void stop() throws LifecycleException {\r
-\r
- // Validate and update our current state\r
- if (!started) {\r
- log.error(sm.getString("coyoteConnector.notStarted"));\r
- return;\r
-\r
- }\r
- lifecycle.fireLifecycleEvent(STOP_EVENT, null);\r
- started = false;\r
-\r
- try {\r
- mapperListener.destroy();\r
- Registry.getRegistry(null, null).unregisterComponent\r
- (createObjectName(this.domain,"Mapper"));\r
- Registry.getRegistry(null, null).unregisterComponent\r
- (createObjectName(this.domain,"ProtocolHandler"));\r
- } catch (MalformedObjectNameException e) {\r
- log.error( sm.getString\r
- ("coyoteConnector.protocolUnregistrationFailed"), e);\r
- }\r
- try {\r
- protocolHandler.destroy();\r
- } catch (Exception e) {\r
- throw new LifecycleException\r
- (sm.getString\r
- ("coyoteConnector.protocolHandlerDestroyFailed", e));\r
- }\r
-\r
- }\r
-\r
-\r
- // -------------------- JMX registration --------------------\r
- protected String domain;\r
- protected ObjectName oname;\r
- protected MBeanServer mserver;\r
- ObjectName controller;\r
-\r
- public ObjectName getController() {\r
- return controller;\r
- }\r
-\r
- public void setController(ObjectName controller) {\r
- this.controller = controller;\r
- }\r
-\r
- public ObjectName getObjectName() {\r
- return oname;\r
- }\r
-\r
- public String getDomain() {\r
- return domain;\r
- }\r
-\r
- public ObjectName preRegister(MBeanServer server,\r
- ObjectName name) throws Exception {\r
- oname=name;\r
- mserver=server;\r
- domain=name.getDomain();\r
- return name;\r
- }\r
-\r
- public void postRegister(Boolean registrationDone) {\r
- }\r
-\r
- public void preDeregister() throws Exception {\r
- }\r
-\r
- public void postDeregister() {\r
- try {\r
- if( started ) {\r
- stop();\r
- }\r
- } catch( Throwable t ) {\r
- log.error( "Unregistering - can't stop", t);\r
- }\r
- }\r
- \r
- protected void findContainer() {\r
- try {\r
- // Register to the service\r
- ObjectName parentName=new ObjectName( domain + ":" +\r
- "type=Service");\r
- \r
- if(log.isDebugEnabled())\r
- log.debug("Adding to " + parentName );\r
- if( mserver.isRegistered(parentName )) {\r
- mserver.invoke(parentName, "addConnector", new Object[] { this },\r
- new String[] {"org.apache.catalina.connector.Connector"});\r
- // As a side effect we'll get the container field set\r
- // Also initialize will be called\r
- //return;\r
- }\r
- // XXX Go directly to the Engine\r
- // initialize(); - is called by addConnector\r
- ObjectName engName=new ObjectName( domain + ":" + "type=Engine");\r
- if( mserver.isRegistered(engName )) {\r
- Object obj=mserver.getAttribute(engName, "managedResource");\r
- if(log.isDebugEnabled())\r
- log.debug("Found engine " + obj + " " + obj.getClass());\r
- container=(Container)obj;\r
- \r
- // Internal initialize - we now have the Engine\r
- initialize();\r
- \r
- if(log.isDebugEnabled())\r
- log.debug("Initialized");\r
- // As a side effect we'll get the container field set\r
- // Also initialize will be called\r
- return;\r
- }\r
- } catch( Exception ex ) {\r
- log.error( "Error finding container " + ex);\r
- }\r
- }\r
-\r
- public void init() throws Exception {\r
-\r
- if( this.getService() != null ) {\r
- if(log.isDebugEnabled())\r
- log.debug( "Already configured" );\r
- return;\r
- }\r
- if( container==null ) {\r
- findContainer();\r
- }\r
- }\r
-\r
- public void destroy() throws Exception {\r
- if( oname!=null && controller==oname ) {\r
- if(log.isDebugEnabled())\r
- log.debug("Unregister itself " + oname );\r
- Registry.getRegistry(null, null).unregisterComponent(oname);\r
- }\r
- if( getService() == null)\r
- return;\r
- getService().removeConnector(this);\r
- }\r
-\r
-}\r
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.catalina.connector;
+
+import java.lang.reflect.Method;
+import java.net.URLEncoder;
+import java.util.HashMap;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Service;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.util.LifecycleSupport;
+import org.apache.catalina.util.StringManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.coyote.Adapter;
+import org.apache.coyote.ProtocolHandler;
+import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tomcat.util.http.mapper.Mapper;
+import org.apache.tomcat.util.modeler.Registry;
+
+
+/**
+ * Implementation of a Coyote connector for Tomcat 5.x.
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+ * @version $Revision: 349505 $ $Date: 2005-11-28 22:14:21 +0100 (lun., 28 nov. 2005) $
+ */
+
+
+public class Connector
+ implements Lifecycle, MBeanRegistration
+{
+ private static Log log = LogFactory.getLog(Connector.class);
+
+
+ // ------------------------------------------------------------ Constructor
+
+
+ public Connector()
+ throws Exception {
+ this(null);
+ }
+
+ public Connector(String protocol)
+ throws Exception {
+ setProtocol(protocol);
+ // Instantiate protocol handler
+ try {
+ Class clazz = Class.forName(protocolHandlerClassName);
+ this.protocolHandler = (ProtocolHandler) clazz.newInstance();
+ } catch (Exception e) {
+ log.error
+ (sm.getString
+ ("coyoteConnector.protocolHandlerInstantiationFailed", e));
+ }
+ }
+
+
+ // ----------------------------------------------------- Instance Variables
+
+
+ /**
+ * The <code>Service</code> we are associated with (if any).
+ */
+ protected Service service = null;
+
+
+ /**
+ * Do we allow TRACE ?
+ */
+ protected boolean allowTrace = false;
+
+
+ /**
+ * The Container used for processing requests received by this Connector.
+ */
+ protected Container container = null;
+
+
+ /**
+ * Use "/" as path for session cookies ?
+ */
+ protected boolean emptySessionPath = false;
+
+
+ /**
+ * The "enable DNS lookups" flag for this Connector.
+ */
+ protected boolean enableLookups = false;
+
+
+ /*
+ * Is generation of X-Powered-By response header enabled/disabled?
+ */
+ protected boolean xpoweredBy = false;
+
+
+ /**
+ * Descriptive information about this Connector implementation.
+ */
+ protected static final String info =
+ "org.apache.catalina.connector.Connector/2.1";
+
+
+ /**
+ * The lifecycle event support for this component.
+ */
+ protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+
+ /**
+ * The port number on which we listen for requests.
+ */
+ protected int port = 0;
+
+
+ /**
+ * The server name to which we should pretend requests to this Connector
+ * were directed. This is useful when operating Tomcat behind a proxy
+ * server, so that redirects get constructed accurately. If not specified,
+ * the server name included in the <code>Host</code> header is used.
+ */
+ protected String proxyName = null;
+
+
+ /**
+ * The server port to which we should pretent requests to this Connector
+ * were directed. This is useful when operating Tomcat behind a proxy
+ * server, so that redirects get constructed accurately. If not specified,
+ * the port number specified by the <code>port</code> property is used.
+ */
+ protected int proxyPort = 0;
+
+
+ /**
+ * The redirect port for non-SSL to SSL redirects.
+ */
+ protected int redirectPort = 443;
+
+
+ /**
+ * The request scheme that will be set on all requests received
+ * through this connector.
+ */
+ protected String scheme = "http";
+
+
+ /**
+ * The secure connection flag that will be set on all requests received
+ * through this connector.
+ */
+ protected boolean secure = false;
+
+
+ /**
+ * The string manager for this package.
+ */
+ protected StringManager sm =
+ StringManager.getManager(Constants.Package);
+
+
+ /**
+ * Maximum size of a POST which will be automatically parsed by the
+ * container. 2MB by default.
+ */
+ protected int maxPostSize = 2 * 1024 * 1024;
+
+
+ /**
+ * Maximum size of a POST which will be saved by the container
+ * during authentication. 4kB by default
+ */
+ protected int maxSavePostSize = 4 * 1024;
+
+
+ /**
+ * Has this component been initialized yet?
+ */
+ protected boolean initialized = false;
+
+
+ /**
+ * Has this component been started yet?
+ */
+ protected boolean started = false;
+
+
+ /**
+ * The shutdown signal to our background thread
+ */
+ protected boolean stopped = false;
+
+ /**
+ * Flag to use IP-based virtual hosting.
+ */
+ protected boolean useIPVHosts = false;
+
+ /**
+ * The background thread.
+ */
+ protected Thread thread = null;
+
+
+ /**
+ * Coyote Protocol handler class name.
+ * Defaults to the Coyote HTTP/1.1 protocolHandler.
+ */
+ protected String protocolHandlerClassName =
+ "org.apache.coyote.http11.Http11Protocol";
+
+
+ /**
+ * Coyote protocol handler.
+ */
+ protected ProtocolHandler protocolHandler = null;
+
+
+ /**
+ * Coyote adapter.
+ */
+ protected Adapter adapter = null;
+
+
+ /**
+ * Mapper.
+ */
+ protected Mapper mapper = new Mapper();
+
+
+ /**
+ * Mapper listener.
+ */
+ protected MapperListener mapperListener = new MapperListener(mapper);
+
+
+ /**
+ * URI encoding.
+ */
+ protected String URIEncoding = null;
+
+
+ /**
+ * URI encoding as body.
+ */
+ protected boolean useBodyEncodingForURI = false;
+
+
+ protected static HashMap replacements = new HashMap();
+ static {
+ replacements.put("acceptCount", "backlog");
+ replacements.put("connectionLinger", "soLinger");
+ replacements.put("connectionTimeout", "soTimeout");
+ replacements.put("connectionUploadTimeout", "timeout");
+ replacements.put("clientAuth", "clientauth");
+ replacements.put("keystoreFile", "keystore");
+ replacements.put("randomFile", "randomfile");
+ replacements.put("rootFile", "rootfile");
+ replacements.put("keystorePass", "keypass");
+ replacements.put("keystoreType", "keytype");
+ replacements.put("sslProtocol", "protocol");
+ replacements.put("sslProtocols", "protocols");
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * Return a configured property.
+ */
+ public Object getProperty(String name) {
+ String repl = name;
+ if (replacements.get(name) != null) {
+ repl = (String) replacements.get(name);
+ }
+ return IntrospectionUtils.getProperty(protocolHandler, repl);
+ }
+
+
+ /**
+ * Set a configured property.
+ */
+ public void setProperty(String name, String value) {
+ String repl = name;
+ if (replacements.get(name) != null) {
+ repl = (String) replacements.get(name);
+ }
+ IntrospectionUtils.setProperty(protocolHandler, repl, value);
+ }
+
+
+ /**
+ * Return a configured property.
+ */
+ public Object getAttribute(String name) {
+ return getProperty(name);
+ }
+
+
+ /**
+ * Set a configured property.
+ */
+ public void setAttribute(String name, Object value) {
+ setProperty(name, String.valueOf(value));
+ }
+
+
+ /**
+ * remove a configured property.
+ */
+ public void removeProperty(String name) {
+ // FIXME !
+ //protocolHandler.removeAttribute(name);
+ }
+
+
+ /**
+ * Return the <code>Service</code> with which we are associated (if any).
+ */
+ public Service getService() {
+
+ return (this.service);
+
+ }
+
+
+ /**
+ * Set the <code>Service</code> with which we are associated (if any).
+ *
+ * @param service The service that owns this Engine
+ */
+ public void setService(Service service) {
+
+ this.service = service;
+ // FIXME: setProperty("service", service);
+
+ }
+
+
+ /**
+ * True if the TRACE method is allowed. Default value is "false".
+ */
+ public boolean getAllowTrace() {
+
+ return (this.allowTrace);
+
+ }
+
+
+ /**
+ * Set the allowTrace flag, to disable or enable the TRACE HTTP method.
+ *
+ * @param allowTrace The new allowTrace flag
+ */
+ public void setAllowTrace(boolean allowTrace) {
+
+ this.allowTrace = allowTrace;
+ setProperty("allowTrace", String.valueOf(allowTrace));
+
+ }
+
+ /**
+ * Is this connector available for processing requests?
+ */
+ public boolean isAvailable() {
+
+ return (started);
+
+ }
+
+
+ /**
+ * Return the input buffer size for this Connector.
+ *
+ * @deprecated
+ */
+ public int getBufferSize() {
+ return 2048;
+ }
+
+ /**
+ * Set the input buffer size for this Connector.
+ *
+ * @param bufferSize The new input buffer size.
+ * @deprecated
+ */
+ public void setBufferSize(int bufferSize) {
+ }
+
+
+ /**
+ * Return the Container used for processing requests received by this
+ * Connector.
+ */
+ public Container getContainer() {
+ if( container==null ) {
+ // Lazy - maybe it was added later
+ findContainer();
+ }
+ return (container);
+
+ }
+
+
+ /**
+ * Set the Container used for processing requests received by this
+ * Connector.
+ *
+ * @param container The new Container to use
+ */
+ public void setContainer(Container container) {
+
+ this.container = container;
+
+ }
+
+
+ /**
+ * Return the "empty session path" flag.
+ */
+ public boolean getEmptySessionPath() {
+
+ return (this.emptySessionPath);
+
+ }
+
+
+ /**
+ * Set the "empty session path" flag.
+ *
+ * @param emptySessionPath The new "empty session path" flag value
+ */
+ public void setEmptySessionPath(boolean emptySessionPath) {
+
+ this.emptySessionPath = emptySessionPath;
+ setProperty("emptySessionPath", String.valueOf(emptySessionPath));
+
+ }
+
+
+ /**
+ * Return the "enable DNS lookups" flag.
+ */
+ public boolean getEnableLookups() {
+
+ return (this.enableLookups);
+
+ }
+
+
+ /**
+ * Set the "enable DNS lookups" flag.
+ *
+ * @param enableLookups The new "enable DNS lookups" flag value
+ */
+ public void setEnableLookups(boolean enableLookups) {
+
+ this.enableLookups = enableLookups;
+ setProperty("enableLookups", String.valueOf(enableLookups));
+
+ }
+
+
+ /**
+ * Return descriptive information about this Connector implementation.
+ */
+ public String getInfo() {
+
+ return (info);
+
+ }
+
+
+ /**
+ * Return the mapper.
+ */
+ public Mapper getMapper() {
+
+ return (mapper);
+
+ }
+
+
+ /**
+ * Return the maximum size of a POST which will be automatically
+ * parsed by the container.
+ */
+ public int getMaxPostSize() {
+
+ return (maxPostSize);
+
+ }
+
+
+ /**
+ * Set the maximum size of a POST which will be automatically
+ * parsed by the container.
+ *
+ * @param maxPostSize The new maximum size in bytes of a POST which will
+ * be automatically parsed by the container
+ */
+ public void setMaxPostSize(int maxPostSize) {
+
+ this.maxPostSize = maxPostSize;
+ }
+
+
+ /**
+ * Return the maximum size of a POST which will be saved by the container
+ * during authentication.
+ */
+ public int getMaxSavePostSize() {
+
+ return (maxSavePostSize);
+
+ }
+
+
+ /**
+ * Set the maximum size of a POST which will be saved by the container
+ * during authentication.
+ *
+ * @param maxSavePostSize The new maximum size in bytes of a POST which will
+ * be saved by the container during authentication.
+ */
+ public void setMaxSavePostSize(int maxSavePostSize) {
+
+ this.maxSavePostSize = maxSavePostSize;
+ setProperty("maxSavePostSize", String.valueOf(maxSavePostSize));
+ }
+
+
+ /**
+ * Return the port number on which we listen for requests.
+ */
+ public int getPort() {
+
+ return (this.port);
+
+ }
+
+
+ /**
+ * Set the port number on which we listen for requests.
+ *
+ * @param port The new port number
+ */
+ public void setPort(int port) {
+
+ this.port = port;
+ setProperty("port", String.valueOf(port));
+
+ }
+
+
+ /**
+ * Return the Coyote protocol handler in use.
+ */
+ public String getProtocol() {
+
+ if ("org.apache.coyote.http11.Http11Protocol".equals
+ (getProtocolHandlerClassName())
+ || "org.apache.coyote.http11.Http11AprProtocol".equals
+ (getProtocolHandlerClassName())) {
+ return "HTTP/1.1";
+ } else if ("org.apache.jk.server.JkCoyoteHandler".equals
+ (getProtocolHandlerClassName())
+ || "org.apache.coyote.ajp.AjpAprProtocol".equals
+ (getProtocolHandlerClassName())) {
+ return "AJP/1.3";
+ }
+ return getProtocolHandlerClassName();
+
+ }
+
+
+ /**
+ * Set the Coyote protocol which will be used by the connector.
+ *
+ * @param protocol The Coyote protocol name
+ */
+ public void setProtocol(String protocol) {
+
+ // Test APR support
+ boolean apr = false;
+ try {
+ String methodName = "initialize";
+ Class paramTypes[] = new Class[1];
+ paramTypes[0] = String.class;
+ Object paramValues[] = new Object[1];
+ paramValues[0] = null;
+ Method method = Class.forName("org.apache.tomcat.jni.Library")
+ .getMethod(methodName, paramTypes);
+ method.invoke(null, paramValues);
+ apr = true;
+ } catch (Throwable t) {
+ // Ignore
+ }
+
+ if (apr) {
+ if ("HTTP/1.1".equals(protocol)) {
+ setProtocolHandlerClassName
+ ("org.apache.coyote.http11.Http11AprProtocol");
+ } else if ("AJP/1.3".equals(protocol)) {
+ setProtocolHandlerClassName
+ ("org.apache.coyote.ajp.AjpAprProtocol");
+ } else if (protocol != null) {
+ setProtocolHandlerClassName(protocol);
+ } else {
+ setProtocolHandlerClassName
+ ("org.apache.coyote.http11.Http11AprProtocol");
+ }
+ } else {
+ if ("HTTP/1.1".equals(protocol)) {
+ setProtocolHandlerClassName
+ ("org.apache.coyote.http11.Http11Protocol");
+ } else if ("AJP/1.3".equals(protocol)) {
+ setProtocolHandlerClassName
+ ("org.apache.jk.server.JkCoyoteHandler");
+ } else if (protocol != null) {
+ setProtocolHandlerClassName(protocol);
+ }
+ }
+
+ }
+
+
+ /**
+ * Return the class name of the Coyote protocol handler in use.
+ */
+ public String getProtocolHandlerClassName() {
+
+ return (this.protocolHandlerClassName);
+
+ }
+
+
+ /**
+ * Set the class name of the Coyote protocol handler which will be used
+ * by the connector.
+ *
+ * @param protocolHandlerClassName The new class name
+ */
+ public void setProtocolHandlerClassName(String protocolHandlerClassName) {
+
+ this.protocolHandlerClassName = protocolHandlerClassName;
+
+ }
+
+
+ /**
+ * Return the protocol handler associated with the connector.
+ */
+ public ProtocolHandler getProtocolHandler() {
+
+ return (this.protocolHandler);
+
+ }
+
+
+ /**
+ * Return the proxy server name for this Connector.
+ */
+ public String getProxyName() {
+
+ return (this.proxyName);
+
+ }
+
+
+ /**
+ * Set the proxy server name for this Connector.
+ *
+ * @param proxyName The new proxy server name
+ */
+ public void setProxyName(String proxyName) {
+
+ if(proxyName != null && proxyName.length() > 0) {
+ this.proxyName = proxyName;
+ setProperty("proxyName", proxyName);
+ } else {
+ this.proxyName = null;
+ removeProperty("proxyName");
+ }
+
+ }
+
+
+ /**
+ * Return the proxy server port for this Connector.
+ */
+ public int getProxyPort() {
+
+ return (this.proxyPort);
+
+ }
+
+
+ /**
+ * Set the proxy server port for this Connector.
+ *
+ * @param proxyPort The new proxy server port
+ */
+ public void setProxyPort(int proxyPort) {
+
+ this.proxyPort = proxyPort;
+ setProperty("proxyPort", String.valueOf(proxyPort));
+
+ }
+
+
+ /**
+ * Return the port number to which a request should be redirected if
+ * it comes in on a non-SSL port and is subject to a security constraint
+ * with a transport guarantee that requires SSL.
+ */
+ public int getRedirectPort() {
+
+ return (this.redirectPort);
+
+ }
+
+
+ /**
+ * Set the redirect port number.
+ *
+ * @param redirectPort The redirect port number (non-SSL to SSL)
+ */
+ public void setRedirectPort(int redirectPort) {
+
+ this.redirectPort = redirectPort;
+ setProperty("redirectPort", String.valueOf(redirectPort));
+
+ }
+
+
+ /**
+ * Return the scheme that will be assigned to requests received
+ * through this connector. Default value is "http".
+ */
+ public String getScheme() {
+
+ return (this.scheme);
+
+ }
+
+
+ /**
+ * Set the scheme that will be assigned to requests received through
+ * this connector.
+ *
+ * @param scheme The new scheme
+ */
+ public void setScheme(String scheme) {
+
+ this.scheme = scheme;
+
+ }
+
+
+ /**
+ * Return the secure connection flag that will be assigned to requests
+ * received through this connector. Default value is "false".
+ */
+ public boolean getSecure() {
+
+ return (this.secure);
+
+ }
+
+
+ /**
+ * Set the secure connection flag that will be assigned to requests
+ * received through this connector.
+ *
+ * @param secure The new secure connection flag
+ */
+ public void setSecure(boolean secure) {
+
+ this.secure = secure;
+ setProperty("secure", Boolean.toString(secure));
+ }
+
+ /**
+ * Return the character encoding to be used for the URI.
+ */
+ public String getURIEncoding() {
+
+ return (this.URIEncoding);
+
+ }
+
+
+ /**
+ * Set the URI encoding to be used for the URI.
+ *
+ * @param URIEncoding The new URI character encoding.
+ */
+ public void setURIEncoding(String URIEncoding) {
+
+ this.URIEncoding = URIEncoding;
+ setProperty("uRIEncoding", URIEncoding);
+
+ }
+
+
+ /**
+ * Return the true if the entity body encoding should be used for the URI.
+ */
+ public boolean getUseBodyEncodingForURI() {
+
+ return (this.useBodyEncodingForURI);
+
+ }
+
+
+ /**
+ * Set if the entity body encoding should be used for the URI.
+ *
+ * @param useBodyEncodingForURI The new value for the flag.
+ */
+ public void setUseBodyEncodingForURI(boolean useBodyEncodingForURI) {
+
+ this.useBodyEncodingForURI = useBodyEncodingForURI;
+ setProperty
+ ("useBodyEncodingForURI", String.valueOf(useBodyEncodingForURI));
+
+ }
+
+
+ /**
+ * Indicates whether the generation of an X-Powered-By response header for
+ * servlet-generated responses is enabled or disabled for this Connector.
+ *
+ * @return true if generation of X-Powered-By response header is enabled,
+ * false otherwise
+ */
+ public boolean getXpoweredBy() {
+ return xpoweredBy;
+ }
+
+
+ /**
+ * Enables or disables the generation of an X-Powered-By header (with value
+ * Servlet/2.4) for all servlet-generated responses returned by this
+ * Connector.
+ *
+ * @param xpoweredBy true if generation of X-Powered-By response header is
+ * to be enabled, false otherwise
+ */
+ public void setXpoweredBy(boolean xpoweredBy) {
+ this.xpoweredBy = xpoweredBy;
+ setProperty("xpoweredBy", String.valueOf(xpoweredBy));
+ }
+
+ /**
+ * Enable the use of IP-based virtual hosting.
+ *
+ * @param useIPVHosts <code>true</code> if Hosts are identified by IP,
+ * <code>false/code> if Hosts are identified by name.
+ */
+ public void setUseIPVHosts(boolean useIPVHosts) {
+ this.useIPVHosts = useIPVHosts;
+ setProperty("useIPVHosts", String.valueOf(useIPVHosts));
+ }
+
+ /**
+ * Test if IP-based virtual hosting is enabled.
+ */
+ public boolean getUseIPVHosts() {
+ return useIPVHosts;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+
+ /**
+ * Create (or allocate) and return a Request object suitable for
+ * specifying the contents of a Request to the responsible Container.
+ */
+ public Request createRequest() {
+
+ Request request = new Request();
+ request.setConnector(this);
+ return (request);
+
+ }
+
+
+ /**
+ * Create (or allocate) and return a Response object suitable for
+ * receiving the contents of a Response from the responsible Container.
+ */
+ public Response createResponse() {
+
+ Response response = new Response();
+ response.setConnector(this);
+ return (response);
+
+ }
+
+
+ // ------------------------------------------------------ Lifecycle Methods
+
+
+ /**
+ * Add a lifecycle event listener to this component.
+ *
+ * @param listener The listener to add
+ */
+ public void addLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.addLifecycleListener(listener);
+
+ }
+
+
+ /**
+ * Get the lifecycle listeners associated with this lifecycle. If this
+ * Lifecycle has no listeners registered, a zero-length array is returned.
+ */
+ public LifecycleListener[] findLifecycleListeners() {
+
+ return lifecycle.findLifecycleListeners();
+
+ }
+
+
+ /**
+ * Remove a lifecycle event listener from this component.
+ *
+ * @param listener The listener to add
+ */
+ public void removeLifecycleListener(LifecycleListener listener) {
+
+ lifecycle.removeLifecycleListener(listener);
+
+ }
+
+
+ protected ObjectName createObjectName(String domain, String type)
+ throws MalformedObjectNameException {
+ String encodedAddr = null;
+ if (getProperty("address") != null) {
+ encodedAddr = URLEncoder.encode(getProperty("address").toString());
+ }
+ String addSuffix = (getProperty("address") == null) ? "" : ",address="
+ + encodedAddr;
+ ObjectName _oname = new ObjectName(domain + ":type=" + type + ",port="
+ + getPort() + addSuffix);
+ return _oname;
+ }
+
+ /**
+ * Initialize this connector (create ServerSocket here!)
+ */
+ public void initialize()
+ throws LifecycleException
+ {
+ if (initialized) {
+ if(log.isInfoEnabled())
+ log.info(sm.getString("coyoteConnector.alreadyInitialized"));
+ return;
+ }
+
+ this.initialized = true;
+
+ if( oname == null && (container instanceof StandardEngine)) {
+ try {
+ // we are loaded directly, via API - and no name was given to us
+ StandardEngine cb=(StandardEngine)container;
+ oname = createObjectName(cb.getName(), "Connector");
+ Registry.getRegistry(null, null)
+ .registerComponent(this, oname, null);
+ controller=oname;
+ } catch (Exception e) {
+ log.error( "Error registering connector ", e);
+ }
+ if(log.isDebugEnabled())
+ log.debug("Creating name for connector " + oname);
+ }
+
+ // Initializa adapter
+ adapter = new CoyoteAdapter(this);
+ protocolHandler.setAdapter(adapter);
+
+ IntrospectionUtils.setProperty(protocolHandler, "jkHome",
+ System.getProperty("catalina.base"));
+
+ try {
+ protocolHandler.init();
+ } catch (Exception e) {
+ throw new LifecycleException
+ (sm.getString
+ ("coyoteConnector.protocolHandlerInitializationFailed", e));
+ }
+ }
+
+
+ /**
+ * Pause the connector.
+ */
+ public void pause()
+ throws LifecycleException {
+ try {
+ protocolHandler.pause();
+ } catch (Exception e) {
+ log.error(sm.getString
+ ("coyoteConnector.protocolHandlerPauseFailed"), e);
+ }
+ }
+
+
+ /**
+ * Pause the connector.
+ */
+ public void resume()
+ throws LifecycleException {
+ try {
+ protocolHandler.resume();
+ } catch (Exception e) {
+ log.error(sm.getString
+ ("coyoteConnector.protocolHandlerResumeFailed"), e);
+ }
+ }
+
+
+ /**
+ * Begin processing requests via this Connector.
+ *
+ * @exception LifecycleException if a fatal startup error occurs
+ */
+ public void start() throws LifecycleException {
+ if( !initialized )
+ initialize();
+
+ // Validate and update our current state
+ if (started ) {
+ if(log.isInfoEnabled())
+ log.info(sm.getString("coyoteConnector.alreadyStarted"));
+ return;
+ }
+ lifecycle.fireLifecycleEvent(START_EVENT, null);
+ started = true;
+
+ // We can't register earlier - the JMX registration of this happens
+ // in Server.start callback
+ if ( this.oname != null ) {
+ // We are registred - register the adapter as well.
+ try {
+ Registry.getRegistry(null, null).registerComponent
+ (protocolHandler, createObjectName(this.domain,"ProtocolHandler"), null);
+ } catch (Exception ex) {
+ log.error(sm.getString
+ ("coyoteConnector.protocolRegistrationFailed"), ex);
+ }
+ } else {
+ if(log.isInfoEnabled())
+ log.info(sm.getString
+ ("coyoteConnector.cannotRegisterProtocol"));
+ }
+
+ try {
+ protocolHandler.start();
+ } catch (Exception e) {
+ String errPrefix = "";
+ if(this.service != null) {
+ errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
+ }
+
+ throw new LifecycleException
+ (errPrefix + " " + sm.getString
+ ("coyoteConnector.protocolHandlerStartFailed", e));
+ }
+
+ if( this.domain != null ) {
+ mapperListener.setDomain( domain );
+ //mapperListener.setEngine( service.getContainer().getName() );
+ mapperListener.init();
+ try {
+ ObjectName mapperOname = createObjectName(this.domain,"Mapper");
+ if (log.isDebugEnabled())
+ log.debug(sm.getString(
+ "coyoteConnector.MapperRegistration", mapperOname));
+ Registry.getRegistry(null, null).registerComponent
+ (mapper, mapperOname, "Mapper");
+ } catch (Exception ex) {
+ log.error(sm.getString
+ ("coyoteConnector.protocolRegistrationFailed"), ex);
+ }
+ }
+ }
+
+
+ /**
+ * Terminate processing requests via this Connector.
+ *
+ * @exception LifecycleException if a fatal shutdown error occurs
+ */
+ public void stop() throws LifecycleException {
+
+ // Validate and update our current state
+ if (!started) {
+ log.error(sm.getString("coyoteConnector.notStarted"));
+ return;
+
+ }
+ lifecycle.fireLifecycleEvent(STOP_EVENT, null);
+ started = false;
+
+ try {
+ mapperListener.destroy();
+ Registry.getRegistry(null, null).unregisterComponent
+ (createObjectName(this.domain,"Mapper"));
+ Registry.getRegistry(null, null).unregisterComponent
+ (createObjectName(this.domain,"ProtocolHandler"));
+ } catch (MalformedObjectNameException e) {
+ log.error( sm.getString
+ ("coyoteConnector.protocolUnregistrationFailed"), e);
+ }
+ try {
+ protocolHandler.destroy();
+ } catch (Exception e) {
+ throw new LifecycleException
+ (sm.getString
+ ("coyoteConnector.protocolHandlerDestroyFailed", e));
+ }
+
+ }
+
+
+ // -------------------- JMX registration --------------------
+ protected String domain;
+ protected ObjectName oname;
+ protected MBeanServer mserver;
+ ObjectName controller;
+
+ public ObjectName getController() {
+ return controller;
+ }
+
+ public void setController(ObjectName controller) {
+ this.controller = controller;
+ }
+
+ public ObjectName getObjectName() {
+ return oname;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public ObjectName preRegister(MBeanServer server,
+ ObjectName name) throws Exception {
+ oname=name;
+ mserver=server;
+ domain=name.getDomain();
+ return name;
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ public void preDeregister() throws Exception {
+ }
+
+ public void postDeregister() {
+ try {
+ if( started ) {
+ stop();
+ }
+ } catch( Throwable t ) {
+ log.error( "Unregistering - can't stop", t);
+ }
+ }
+
+ protected void findContainer() {
+ try {
+ // Register to the service
+ ObjectName parentName=new ObjectName( domain + ":" +
+ "type=Service");
+
+ if(log.isDebugEnabled())
+ log.debug("Adding to " + parentName );
+ if( mserver.isRegistered(parentName )) {
+ mserver.invoke(parentName, "addConnector", new Object[] { this },
+ new String[] {"org.apache.catalina.connector.Connector"});
+ // As a side effect we'll get the container field set
+ // Also initialize will be called
+ //return;
+ }
+ // XXX Go directly to the Engine
+ // initialize(); - is called by addConnector
+ ObjectName engName=new ObjectName( domain + ":" + "type=Engine");
+ if( mserver.isRegistered(engName )) {
+ Object obj=mserver.getAttribute(engName, "managedResource");
+ if(log.isDebugEnabled())
+ log.debug("Found engine " + obj + " " + obj.getClass());
+ container=(Container)obj;
+
+ // Internal initialize - we now have the Engine
+ initialize();
+
+ if(log.isDebugEnabled())
+ log.debug("Initialized");
+ // As a side effect we'll get the container field set
+ // Also initialize will be called
+ return;
+ }
+ } catch( Exception ex ) {
+ log.error( "Error finding container " + ex);
+ }
+ }
+
+ public void init() throws Exception {
+
+ if( this.getService() != null ) {
+ if(log.isDebugEnabled())
+ log.debug( "Already configured" );
+ return;
+ }
+ if( container==null ) {
+ findContainer();
+ }
+ }
+
+ public void destroy() throws Exception {
+ if( oname!=null && controller==oname ) {
+ if(log.isDebugEnabled())
+ log.debug("Unregister itself " + oname );
+ Registry.getRegistry(null, null).unregisterComponent(oname);
+ }
+ if( getService() == null)
+ return;
+ getService().removeConnector(this);
+ }
+
+}