| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.catalina.Container; |
| import org.apache.catalina.ContainerEvent; |
| import org.apache.catalina.ContainerListener; |
| import org.apache.catalina.Context; |
| import org.apache.catalina.Engine; |
| import org.apache.catalina.Host; |
| import org.apache.catalina.Lifecycle; |
| import org.apache.catalina.LifecycleEvent; |
| import org.apache.catalina.LifecycleException; |
| import org.apache.catalina.LifecycleListener; |
| import org.apache.catalina.LifecycleState; |
| import org.apache.catalina.Wrapper; |
| import org.apache.catalina.util.LifecycleMBeanBase; |
| import org.apache.juli.logging.Log; |
| import org.apache.juli.logging.LogFactory; |
| import org.apache.tomcat.util.http.mapper.Mapper; |
| import org.apache.tomcat.util.res.StringManager; |
| |
| |
| /** |
| * Mapper listener. |
| * |
| * @author Remy Maucherat |
| * @author Costin Manolache |
| */ |
| public class MapperListener extends LifecycleMBeanBase |
| implements ContainerListener, LifecycleListener { |
| |
| |
| private static final Log log = LogFactory.getLog(MapperListener.class); |
| |
| |
| // ----------------------------------------------------- Instance Variables |
| /** |
| * Associated mapper. |
| */ |
| private Mapper mapper = null; |
| |
| /** |
| * Associated connector |
| */ |
| private Connector connector = null; |
| |
| |
| /** |
| * The string manager for this package. |
| */ |
| private static final StringManager sm = |
| StringManager.getManager(Constants.Package); |
| |
| /** |
| * The domain (effectively the engine) this mapper is associated with |
| */ |
| private String domain = null; |
| |
| // ----------------------------------------------------------- Constructors |
| |
| |
| /** |
| * Create mapper listener. |
| */ |
| public MapperListener(Mapper mapper, Connector connector) { |
| this.mapper = mapper; |
| this.connector = connector; |
| } |
| |
| |
| // --------------------------------------------------------- Public Methods |
| |
| public String getConnectorName() { |
| return this.connector.toString(); |
| } |
| |
| |
| // ------------------------------------------------------- Lifecycle Methods |
| |
| @Override |
| public void startInternal() throws LifecycleException { |
| |
| setState(LifecycleState.STARTING); |
| |
| // Find any components that have already been initialized since the |
| // MBean listener won't be notified as those components will have |
| // already registered their MBeans |
| findDefaultHost(); |
| |
| Engine engine = (Engine) connector.getService().getContainer(); |
| addListeners(engine); |
| |
| Container[] conHosts = engine.findChildren(); |
| for (Container conHost : conHosts) { |
| Host host = (Host) conHost; |
| if (!LifecycleState.NEW.equals(host.getState())) { |
| // Registering the host will register the context and wrappers |
| registerHost(host); |
| } |
| } |
| } |
| |
| |
| @Override |
| public void stopInternal() throws LifecycleException { |
| setState(LifecycleState.STOPPING); |
| } |
| |
| |
| @Override |
| protected String getDomainInternal() { |
| // Should be the same as the connector |
| return connector.getDomainInternal(); |
| } |
| |
| |
| @Override |
| protected String getObjectNameKeyProperties() { |
| // Same as connector but Mapper rather than Connector |
| return connector.createObjectNameKeyProperties("Mapper"); |
| } |
| |
| // --------------------------------------------- Container Listener methods |
| |
| @Override |
| public void containerEvent(ContainerEvent event) { |
| |
| if (event.getType() == Container.ADD_CHILD_EVENT) { |
| Container child = (Container) event.getData(); |
| addListeners(child); |
| // If child is started then it is too late for life-cycle listener |
| // to register the child so register it here |
| if (child.getState().isAvailable()) { |
| if (child instanceof Host) { |
| registerHost((Host) child); |
| } else if (child instanceof Context) { |
| registerContext((Context) child); |
| } else if (child instanceof Wrapper) { |
| registerWrapper((Wrapper) child); |
| } |
| } |
| } else if (event.getType() == Container.REMOVE_CHILD_EVENT) { |
| Container child = (Container) event.getData(); |
| removeListeners(child); |
| // No need to unregister - life-cycle listener will handle this when |
| // the child stops |
| } else if (event.getType() == Host.ADD_ALIAS_EVENT) { |
| // Handle dynamically adding host aliases |
| mapper.addHostAlias(((Host) event.getSource()).getName(), |
| event.getData().toString()); |
| } else if (event.getType() == Host.REMOVE_ALIAS_EVENT) { |
| // Handle dynamically removing host aliases |
| mapper.removeHostAlias(event.getData().toString()); |
| } else if (event.getType() == Wrapper.ADD_MAPPING_EVENT) { |
| // Handle dynamically adding wrappers |
| Wrapper wrapper = (Wrapper) event.getSource(); |
| Context context = (Context) wrapper.getParent(); |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| String version = ((Context) wrapper.getParent()).getWebappVersion(); |
| String hostName = context.getParent().getName(); |
| String wrapperName = wrapper.getName(); |
| String mapping = (String) event.getData(); |
| boolean jspWildCard = ("jsp".equals(wrapperName) |
| && mapping.endsWith("/*")); |
| mapper.addWrapper(hostName, contextPath, version, mapping, wrapper, |
| jspWildCard, context.isResourceOnlyServlet(wrapperName)); |
| } else if (event.getType() == Wrapper.REMOVE_MAPPING_EVENT) { |
| // Handle dynamically removing wrappers |
| Wrapper wrapper = (Wrapper) event.getSource(); |
| |
| String contextPath = ((Context) wrapper.getParent()).getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| String version = ((Context) wrapper.getParent()).getWebappVersion(); |
| String hostName = wrapper.getParent().getParent().getName(); |
| |
| String mapping = (String) event.getData(); |
| |
| mapper.removeWrapper(hostName, contextPath, version, mapping); |
| } else if (event.getType() == Context.ADD_WELCOME_FILE_EVENT) { |
| // Handle dynamically adding welcome files |
| Context context = (Context) event.getSource(); |
| |
| String hostName = context.getParent().getName(); |
| |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| |
| String welcomeFile = (String) event.getData(); |
| |
| mapper.addWelcomeFile(hostName, contextPath, |
| context.getWebappVersion(), welcomeFile); |
| } else if (event.getType() == Context.REMOVE_WELCOME_FILE_EVENT) { |
| // Handle dynamically removing welcome files |
| Context context = (Context) event.getSource(); |
| |
| String hostName = context.getParent().getName(); |
| |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| |
| String welcomeFile = (String) event.getData(); |
| |
| mapper.removeWelcomeFile(hostName, contextPath, |
| context.getWebappVersion(), welcomeFile); |
| } else if (event.getType() == Context.CLEAR_WELCOME_FILES_EVENT) { |
| // Handle dynamically clearing welcome files |
| Context context = (Context) event.getSource(); |
| |
| String hostName = context.getParent().getName(); |
| |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| |
| mapper.clearWelcomeFiles(hostName, contextPath, |
| context.getWebappVersion()); |
| } |
| } |
| |
| |
| // ------------------------------------------------------ Protected Methods |
| |
| private void findDefaultHost() { |
| |
| Engine engine = (Engine) connector.getService().getContainer(); |
| String defaultHost = engine.getDefaultHost(); |
| |
| boolean found = false; |
| |
| if (defaultHost != null && defaultHost.length() >0) { |
| Container[] containers = engine.findChildren(); |
| |
| for (Container container : containers) { |
| Host host = (Host) container; |
| if (defaultHost.equalsIgnoreCase(host.getName())) { |
| found = true; |
| break; |
| } |
| |
| String[] aliases = host.findAliases(); |
| for (String alias : aliases) { |
| if (defaultHost.equalsIgnoreCase(alias)) { |
| found = true; |
| break; |
| } |
| } |
| } |
| } |
| |
| if(found) { |
| mapper.setDefaultHostName(defaultHost); |
| } else { |
| log.warn(sm.getString("mapperListener.unknownDefaultHost", |
| defaultHost, connector)); |
| } |
| } |
| |
| |
| /** |
| * Register host. |
| */ |
| private void registerHost(Host host) { |
| |
| String[] aliases = host.findAliases(); |
| mapper.addHost(host.getName(), aliases, host); |
| |
| for (Container container : host.findChildren()) { |
| if (container.getState().isAvailable()) { |
| registerContext((Context) container); |
| } |
| } |
| if(log.isDebugEnabled()) { |
| log.debug(sm.getString("mapperListener.registerHost", |
| host.getName(), domain, connector)); |
| } |
| } |
| |
| |
| /** |
| * Unregister host. |
| */ |
| private void unregisterHost(Host host) { |
| |
| String hostname = host.getName(); |
| |
| mapper.removeHost(hostname); |
| |
| if(log.isDebugEnabled()) |
| log.debug(sm.getString("mapperListener.unregisterHost", hostname, |
| domain, connector)); |
| } |
| |
| |
| /** |
| * Unregister wrapper. |
| */ |
| private void unregisterWrapper(Wrapper wrapper) { |
| |
| String contextPath = ((Context) wrapper.getParent()).getPath(); |
| String wrapperName = wrapper.getName(); |
| |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| String version = ((Context) wrapper.getParent()).getWebappVersion(); |
| String hostName = wrapper.getParent().getParent().getName(); |
| |
| String[] mappings = wrapper.findMappings(); |
| |
| for (String mapping : mappings) { |
| mapper.removeWrapper(hostName, contextPath, version, mapping); |
| } |
| |
| if(log.isDebugEnabled()) { |
| log.debug(sm.getString("mapperListener.unregisterWrapper", |
| wrapperName, contextPath, connector)); |
| } |
| } |
| |
| |
| /** |
| * Register context. |
| */ |
| private void registerContext(Context context) { |
| |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| Container host = context.getParent(); |
| |
| javax.naming.Context resources = context.getResources(); |
| String[] welcomeFiles = context.findWelcomeFiles(); |
| |
| mapper.addContextVersion(host.getName(), host, contextPath, |
| context.getWebappVersion(), context, welcomeFiles, resources); |
| |
| for (Container container : context.findChildren()) { |
| registerWrapper((Wrapper) container); |
| } |
| |
| if(log.isDebugEnabled()) { |
| log.debug(sm.getString("mapperListener.registerContext", |
| contextPath, connector)); |
| } |
| } |
| |
| |
| /** |
| * Unregister context. |
| */ |
| private void unregisterContext(Context context) { |
| |
| // Don't un-map a context that is paused |
| if (context.getPaused()){ |
| return; |
| } |
| |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| String hostName = context.getParent().getName(); |
| |
| if(log.isDebugEnabled()) |
| log.debug(sm.getString("mapperListener.unregisterContext", |
| contextPath, connector)); |
| |
| mapper.removeContextVersion(hostName, contextPath, |
| context.getWebappVersion()); |
| } |
| |
| |
| /** |
| * Register wrapper. |
| */ |
| private void registerWrapper(Wrapper wrapper) { |
| |
| String wrapperName = wrapper.getName(); |
| Context context = (Context) wrapper.getParent(); |
| String contextPath = context.getPath(); |
| if ("/".equals(contextPath)) { |
| contextPath = ""; |
| } |
| String version = ((Context) wrapper.getParent()).getWebappVersion(); |
| String hostName = context.getParent().getName(); |
| |
| String[] mappings = wrapper.findMappings(); |
| |
| for (String mapping : mappings) { |
| boolean jspWildCard = (wrapperName.equals("jsp") |
| && mapping.endsWith("/*")); |
| mapper.addWrapper(hostName, contextPath, version, mapping, wrapper, |
| jspWildCard, |
| context.isResourceOnlyServlet(wrapperName)); |
| } |
| |
| if(log.isDebugEnabled()) { |
| log.debug(sm.getString("mapperListener.registerWrapper", |
| wrapperName, contextPath, connector)); |
| } |
| } |
| |
| @Override |
| public void lifecycleEvent(LifecycleEvent event) { |
| if (event.getType() == Lifecycle.AFTER_START_EVENT) { |
| Object obj = event.getSource(); |
| if (obj instanceof Wrapper) { |
| registerWrapper((Wrapper) obj); |
| } else if (obj instanceof Context) { |
| registerContext((Context) obj); |
| } else if (obj instanceof Host) { |
| registerHost((Host) obj); |
| } |
| } else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) { |
| Object obj = event.getSource(); |
| if (obj instanceof Wrapper) { |
| unregisterWrapper((Wrapper) obj); |
| } else if (obj instanceof Context) { |
| unregisterContext((Context) obj); |
| } else if (obj instanceof Host) { |
| unregisterHost((Host) obj); |
| } |
| } |
| } |
| |
| |
| /** |
| * Add this mapper to the container and all child containers |
| * |
| * @param container |
| */ |
| private void addListeners(Container container) { |
| container.addContainerListener(this); |
| container.addLifecycleListener(this); |
| for (Container child : container.findChildren()) { |
| addListeners(child); |
| } |
| } |
| |
| |
| /** |
| * Remove this mapper from the container and all child containers |
| * |
| * @param container |
| */ |
| private void removeListeners(Container container) { |
| container.removeContainerListener(this); |
| container.removeLifecycleListener(this); |
| for (Container child : container.findChildren()) { |
| removeListeners(child); |
| } |
| } |
| } |