diff --git a/scm-core/src/main/java/sonia/scm/boot/RestartEvent.java b/scm-core/src/main/java/sonia/scm/boot/RestartEvent.java new file mode 100644 index 0000000000..244bc8f03c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/boot/RestartEvent.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2014, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.boot; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.Stage; +import sonia.scm.event.Event; + +/** + * This event can be used to force a restart of the webapp context. The restart + * event is useful during plugin development, because we don't have to restart + * the whole server, to see our changes. The restart event can only be used in + * stage {@link Stage#DEVELOPMENT}. + * + * @author Sebastian Sdorra + * @since 2.0.0 + */ +@Event +public class RestartEvent +{ + + /** + * Constructs ... + * + * + * @param cause + * @param reason + */ + public RestartEvent(Class cause, String reason) + { + this.cause = cause; + this.reason = reason; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * The class which has fired the restart event. + * + * + * @return class which has fired the restart event + */ + public Class getCause() + { + return cause; + } + + /** + * Returns the reason for the restart. + * + * + * @return reason for restart + */ + public String getReason() + { + return reason; + } + + //~--- fields --------------------------------------------------------------- + + /** cause of restart */ + private final Class cause; + + /** reason for restart */ + private final String reason; +} diff --git a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextFilter.java b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextFilter.java new file mode 100644 index 0000000000..bfa2218e76 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextFilter.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2014, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.boot; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.github.legman.Subscribe; + +import com.google.inject.servlet.GuiceFilter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.SCMContext; +import sonia.scm.Stage; +import sonia.scm.event.ScmEventBus; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.servlet.FilterConfig; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletException; + +/** + * + * @author Sebastian Sdorra + */ +public class BootstrapContextFilter extends GuiceFilter +{ + + /** + * the logger for BootstrapContextFilter + */ + private static final Logger logger = + LoggerFactory.getLogger(BootstrapContextFilter.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Restart the whole webapp context. + * + * + * @param event restart event + * + * @throws ServletException + */ + @Subscribe(async = false) + public void handleRestartEvent(RestartEvent event) throws ServletException + { + logger.warn("received restart event from {} with reason: {}", + event.getCause(), event.getReason()); + + if (filterConfig == null) + { + logger.error("filter config is null, scm-manager is not initialized"); + } + else + { + + logger.warn( + "destroy filter pipeline, because of a received restart event"); + destroy(); + logger.warn( + "reinitialize filter pipeline, because of a received restart event"); + super.init(filterConfig); + } + } + + /** + * Method description + * + * + * @param filterConfig + * + * @throws ServletException + */ + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + this.filterConfig = filterConfig; + super.init(filterConfig); + + if (SCMContext.getContext().getStage() == Stage.DEVELOPMENT) + { + logger.info("register for restart events"); + ScmEventBus.getInstance().register(this); + } + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private FilterConfig filterConfig; +} diff --git a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java index 96f1a3748e..4f7a00ce56 100644 --- a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapContextListener.java @@ -33,15 +33,20 @@ package sonia.scm.boot; //~--- non-JDK imports -------------------------------------------------------- +import com.github.legman.Subscribe; + import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.io.Files; +import com.google.inject.servlet.GuiceFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.SCMContext; import sonia.scm.ScmContextListener; +import sonia.scm.Stage; +import sonia.scm.event.ScmEventBus; import sonia.scm.plugin.Plugin; import sonia.scm.plugin.PluginException; import sonia.scm.plugin.PluginLoadException; @@ -128,6 +133,7 @@ public class BootstrapContextListener implements ServletContextListener } } + context = null; contextListener = null; } @@ -140,7 +146,8 @@ public class BootstrapContextListener implements ServletContextListener @Override public void contextInitialized(ServletContextEvent sce) { - ServletContext context = sce.getServletContext(); + context = sce.getServletContext(); + PluginIndex index = readCorePluginIndex(context); File pluginDirectory = getPluginDirectory(); @@ -163,6 +170,42 @@ public class BootstrapContextListener implements ServletContextListener } contextListener.contextInitialized(sce); + + // register for restart events + if (!registered + && (SCMContext.getContext().getStage() == Stage.DEVELOPMENT)) + { + logger.info("register for restart events"); + ScmEventBus.getInstance().register(this); + registered = true; + } + } + + /** + * Restart the whole webapp context. + * + * + * @param event restart event + */ + @Subscribe + public void handleRestartEvent(RestartEvent event) + { + logger.warn("received restart event from {} with reason: {}", + event.getCause(), event.getReason()); + + if (context == null) + { + logger.error("context is null, scm-manager is not initialized"); + } + else + { + ServletContextEvent sce = new ServletContextEvent(context); + + logger.warn("destroy context, because of a received restart event"); + contextDestroyed(sce); + logger.warn("reinitialize context, because of a received restart event"); + contextInitialized(sce); + } } /** @@ -391,6 +434,12 @@ public class BootstrapContextListener implements ServletContextListener //~--- fields --------------------------------------------------------------- + /** Field description */ + private ServletContext context; + /** Field description */ private ScmContextListener contextListener; + + /** Field description */ + private boolean registered = false; } diff --git a/scm-webapp/src/main/webapp/WEB-INF/web.xml b/scm-webapp/src/main/webapp/WEB-INF/web.xml index 97ea5d8b32..fb906270a4 100644 --- a/scm-webapp/src/main/webapp/WEB-INF/web.xml +++ b/scm-webapp/src/main/webapp/WEB-INF/web.xml @@ -48,12 +48,12 @@ - guiceFilter - com.google.inject.servlet.GuiceFilter + BootstrapFilter + sonia.scm.boot.BootstrapContextFilter - guiceFilter + BootstrapFilter /*