This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/master by this push: new c5fbb15 Add utility Server listener c5fbb15 is described below commit c5fbb158f7e91306a010dd95f4f13996991dd8fd Author: remm <r...@apache.org> AuthorDate: Tue May 28 16:40:30 2019 +0200 Add utility Server listener Its purpose is to replicate adding a Listener in context.xml. Also add new container events to notify container add and remove before start and after stop (respectively) so that containers can actually be configured before a possible lifecycle change. --- java/org/apache/catalina/Container.java | 14 +++ java/org/apache/catalina/core/ContainerBase.java | 4 + .../apache/catalina/core/FrameworkListener.java | 114 +++++++++++++++++++++ webapps/docs/changelog.xml | 10 ++ 4 files changed, 142 insertions(+) diff --git a/java/org/apache/catalina/Container.java b/java/org/apache/catalina/Container.java index 177b2d2..0b30247 100644 --- a/java/org/apache/catalina/Container.java +++ b/java/org/apache/catalina/Container.java @@ -84,6 +84,13 @@ public interface Container extends Lifecycle { /** * The ContainerEvent event type sent when a child container is added + * by <code>addChild()</code>, but before it is started. + */ + public static final String ADD_CHILD_BEFORE_START_EVENT = "addChildBeforeStart"; + + + /** + * The ContainerEvent event type sent when a child container is added * by <code>addChild()</code>. */ public static final String ADD_CHILD_EVENT = "addChild"; @@ -98,6 +105,13 @@ public interface Container extends Lifecycle { /** * The ContainerEvent event type sent when a child container is removed + * by <code>removeChild()</code>, but before it is stopped. + */ + public static final String REMOVE_CHILD_BEFORE_STOP_EVENT = "removeChildBeforeStop"; + + + /** + * The ContainerEvent event type sent when a child container is removed * by <code>removeChild()</code>. */ public static final String REMOVE_CHILD_EVENT = "removeChild"; diff --git a/java/org/apache/catalina/core/ContainerBase.java b/java/org/apache/catalina/core/ContainerBase.java index cee5e42..f3a3011 100644 --- a/java/org/apache/catalina/core/ContainerBase.java +++ b/java/org/apache/catalina/core/ContainerBase.java @@ -703,6 +703,8 @@ public abstract class ContainerBase extends LifecycleMBeanBase children.put(child.getName(), child); } + fireContainerEvent(ADD_CHILD_BEFORE_START_EVENT, child); + // Start child // Don't do this inside sync block - start can be a slow process and // locking the children object can cause problems elsewhere @@ -798,6 +800,8 @@ public abstract class ContainerBase extends LifecycleMBeanBase return; } + fireContainerEvent(REMOVE_CHILD_BEFORE_STOP_EVENT, child); + try { if (child.getState().isAvailable()) { child.stop(); diff --git a/java/org/apache/catalina/core/FrameworkListener.java b/java/org/apache/catalina/core/FrameworkListener.java new file mode 100644 index 0000000..4927e49 --- /dev/null +++ b/java/org/apache/catalina/core/FrameworkListener.java @@ -0,0 +1,114 @@ +/* + * 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.core; + +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.LifecycleListener; +import org.apache.catalina.Server; +import org.apache.catalina.Service; + +/** + * This listener must be declared in server.xml as a Server listener, possibly optional. + * It will register a lifecycle listener on all contexts. This is an alternative to + * adding a Listener in context.xml with more flexibility. + */ +public abstract class FrameworkListener implements LifecycleListener, ContainerListener { + + /** + * Create a lifecycle listener which will then be added to the specified context. + * @param context the associated Context + * @return the lifecycle listener + */ + protected abstract LifecycleListener createLifecycleListener(Context context); + + @Override + public void lifecycleEvent(LifecycleEvent event) { + Lifecycle lifecycle = event.getLifecycle(); + if (Lifecycle.BEFORE_START_EVENT.equals(event.getType()) && + lifecycle instanceof Server) { + Server server = (Server) lifecycle; + registerListenersForServer(server); + } + } + + @Override + public void containerEvent(ContainerEvent event) { + String type = event.getType(); + if (Container.ADD_CHILD_BEFORE_START_EVENT.equals(type)) { + processContainerAddChild(event.getContainer(), + (Container) event.getData()); + } else if (Container.REMOVE_CHILD_BEFORE_STOP_EVENT.equals(type)) { + processContainerRemoveChild(event.getContainer(), + (Container) event.getData()); + } + } + + private void registerListenersForServer(Server server) { + for (Service service : server.findServices()) { + Engine engine = service.getContainer(); + if (engine != null) { + engine.addContainerListener(this); + registerListenersForEngine(engine); + } + } + + } + + private void registerListenersForEngine(Engine engine) { + for (Container hostContainer : engine.findChildren()) { + Host host = (Host) hostContainer; + host.addContainerListener(this); + registerListenersForHost(host); + } + } + + private void registerListenersForHost(Host host) { + for (Container contextContainer : host.findChildren()) { + Context context = (Context) contextContainer; + registerContextListener(context); + } + } + + private void registerContextListener(Context context) { + context.addLifecycleListener(createLifecycleListener(context)); + } + + private void processContainerAddChild(Container parent, Container child) { + if (child instanceof Context) { + registerContextListener((Context) child); + } else if (child instanceof Engine) { + registerListenersForEngine((Engine) child); + } else if (child instanceof Host) { + registerListenersForHost((Host) child); + } + } + + private void processContainerRemoveChild(Container parent, Container child) { + if (child instanceof Host || child instanceof Engine) { + child.removeContainerListener(this); + } + } + +} diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 5032643..0e40e52 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -80,6 +80,16 @@ Add <code>Context.createInstanceManager()</code> for easier framework integration. (remm) </scode> + <scode> + Add utility <code>org.apache.catalina.core.FrameworkListener</code> to + allow replicating adding a Listener to context.xml in a programmatic + way. (remm) + </scode> + <scode> + Add <code>Container.ADD_CHILD_BEFORE_START_EVENT</code> and + <code>Container.REMOVE_CHILD_BEFORE_STOP_EVENT</code> to allow + configuration of containers before a possible lifecycle event. (remm) + </scode> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org