package de.skuzzle.tinyplugz.guice;

import java.nio.file.Path;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;

import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;

import de.skuzzle.tinyplugz.Require;
import de.skuzzle.tinyplugz.TinyPlugz;
import de.skuzzle.tinyplugz.TinyPlugzConfigurator.DefineProperties;
import de.skuzzle.tinyplugz.TinyPlugzConfigurator.DeployTinyPlugz;
import de.skuzzle.tinyplugz.TinyPlugzServletContextListener;

/**
 * ServletContextListener which uses TinyPlugz for configuring the application's
 * guice {@link Injector}. When receiving the contextInitialized event, this
 * listener will deploy TinyPlugz using the configuration given by
 * {@link #configure(DefineProperties, Path)}. It will then obtain the injector
 * from TinyPlugz and configure the {@link GuiceServletContextListener}
 * appropriately.
 * <p>
 * {@link #tinyPlugzDeployed(TinyPlugz, Injector, ServletContext)} will be
 * called if TinyPlugz and guice have successfully been setup. Its default
 * implementation does nothing and may be overridden e.g. to put additional
 * information into the servlet context.
 *
 * @author Simon Taddiken
 */
public abstract class TinyPlugzGuiceServletContextListener extends
        GuiceServletContextListener {

    private Injector injector;
    private final TinyPlugzServletContextListener delegate =
            new TinyPlugzServletContextListener() {

                @Override
                protected final DeployTinyPlugz configure(DefineProperties props,
                        Path webInfDir) {

                    return TinyPlugzGuiceServletContextListener.this.configure
                            (props, webInfDir);
                }
            };

    /**
     * Configures TinyPlugz. See {@link TinyPlugzServletContextListener}.
     *
     * @param props Builder object for specifying configuration options.
     * @param webInfDir The web application's WEB-INF directory.
     * @return The {@link DeployTinyPlugz} instance returned by
     *         {@link DefineProperties#withPlugins(java.util.function.Consumer)}
     *         .
     */
    protected abstract DeployTinyPlugz configure(DefineProperties props, Path webInfDir);

    /**
     * Called after TinyPlugz and guice have successfully been setup. The
     * default implementation does nothing.
     *
     * @param tinyPlugz The deployed TinyPlugz instance.
     * @param injector The created guice injector.
     * @param ctx The current servlet context.
     */
    protected void tinyPlugzDeployed(TinyPlugz tinyPlugz, Injector injector,
            ServletContext ctx) {
        // do nothing
    }

    @Override
    protected Injector getInjector() {
        Require.state(this.injector != null, "Injector not initialized");
        return this.injector;
    }

    @Override
    public final void contextInitialized(ServletContextEvent servletContextEvent) {
        // this deploys TinyPlugz
        this.delegate.contextInitialized(servletContextEvent);

        this.injector = TinyPlugz.getInstance().getService(Injector.class);
        super.contextInitialized(servletContextEvent);

        tinyPlugzDeployed(TinyPlugz.getInstance(), this.injector,
                servletContextEvent.getServletContext());
    }

    @Override
    public final void contextDestroyed(ServletContextEvent servletContextEvent) {
        this.delegate.contextDestroyed(servletContextEvent);
        super.contextDestroyed(servletContextEvent);
        this.injector = null;
    }
}

@@ -1211,20 +1211,60 @@
 addiken%0A
+ * @see TinyPlugzServletContextListener%0A
  */%0A
-
 public a
@@ -2734,32 +2734,673 @@
  nothing%0A    %7D%0A%0A
+    /**%0A     * Called when this listener receives the context destroyed event. TinyPlugz will not%0A     * be deployed anymore by the time this method is called. The default implementation%0A     * does nothing.%0A     *%0A     * @param ctx The destroyed servlet context.%0A     */%0A    protected void tinyPlugzUndeployed(ServletContext ctx) %7B%0A        // do nothing%0A    %7D%0A%0A    /**%0A     * Returns the guice %7B@link Injector%7D which will be created by TinyPlugz.%0A     * The injector will be made available when this listener receives the%0A     * context initialized event.%0A     *%0A     * @return The guice Injector to use within the web application.%0A     */%0A
     @Override%0A  
@@ -4094,32 +4094,63 @@
 ContextEvent) %7B%0A
+        // undeploy tiny plugz%0A
         this.del
@@ -4185,32 +4185,59 @@
 etContextEvent);
+%0A%0A        // undeploy guice
 %0A        super.c
@@ -4273,16 +4273,87 @@
 tEvent);
+%0A%0A        tinyPlugzUndeployed(servletContextEvent.getServletContext());
 %0A       

Add undeploy listening method