/*
 * Copyright (c) 2010-2012 Engine Yard, Inc.
 * Copyright (c) 2007-2009 Sun Microsystems, Inc.
 * This source code is available under the MIT license.
 * See the file LICENSE.txt for details.
 */

package org.jruby.rack;

import org.jruby.rack.servlet.DefaultServletRackContext;
import org.jruby.rack.servlet.ServletRackConfig;
import org.jruby.rack.servlet.ServletRackContext;

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

/**
 * Web application lifecycle listener.
 * @author nicksieger
 */
public class RackServletContextListener implements ServletContextListener {
    
    private final RackApplicationFactory factory;

    public RackServletContextListener() {
        factory = null;
    }

    /**
     * Not used by servlet container -- only for injecting a mock factory
     * for testing.
     */
    public RackServletContextListener(RackApplicationFactory factoryForTest) {
        factory = factoryForTest;
    }

    public void contextInitialized(ServletContextEvent ctxEvent) {
        ServletContext ctx = ctxEvent.getServletContext();
        ServletRackConfig config = new ServletRackConfig(ctx);
        final RackApplicationFactory fac = newApplicationFactory(config);
        ctx.setAttribute(RackApplicationFactory.FACTORY, fac);
        ServletRackContext rackContext = new DefaultServletRackContext(config);
        ctx.setAttribute(RackApplicationFactory.RACK_CONTEXT, rackContext);
        try {
            fac.init(rackContext);
        } catch (Exception ex) {
            ctx.log("Error: application initialization failed", ex);
        }
    }

    public void contextDestroyed(ServletContextEvent ctxEvent) {
        ServletContext ctx = ctxEvent.getServletContext();
        final RackApplicationFactory fac =
                (RackApplicationFactory) ctx.getAttribute(RackApplicationFactory.FACTORY);
        if (fac != null) {
            fac.destroy();
            ctx.removeAttribute(RackApplicationFactory.FACTORY);
            ctx.removeAttribute(RackApplicationFactory.RACK_CONTEXT);
        }
    }

    protected RackApplicationFactory newApplicationFactory(RackConfig config) {
        if (factory != null) {
            return factory;
        }
        return new SharedRackApplicationFactory(new DefaultRackApplicationFactory());
    }
    
}

@@ -701,16 +701,62 @@
 ctory;%0A%0A
+    /**%0A     * Used by web container.%0A     */%0A
     publ
@@ -789,32 +789,37 @@
 ner() %7B%0A        
+this.
 factory = null;%0A
@@ -844,42 +844,9 @@
   * 
-Not used by servlet container -- o
+O
 nly 
@@ -873,23 +873,16 @@
  factory
-%0A     *
  for tes
@@ -963,23 +963,16 @@
  factory
-ForTest
 ) %7B%0A    
@@ -975,16 +975,21 @@
         
+this.
 factory 
@@ -1001,15 +1001,8 @@
 tory
-ForTest
 ;%0A  
@@ -1041,16 +1041,22 @@
 ialized(
+final 
 ServletC
@@ -1059,36 +1059,33 @@
 letContextEvent 
-ctxE
+e
 vent) %7B%0A        
@@ -1076,32 +1076,38 @@
 vent) %7B%0A        
+final 
 ServletContext c
@@ -1102,33 +1102,34 @@
 letContext c
-tx = ctxE
+ontext = e
 vent.getServ
@@ -1142,32 +1142,38 @@
 text();%0A        
+final 
 ServletRackConfi
@@ -1206,18 +1206,22 @@
 Config(c
+ontex
 t
-x
 );%0A     
@@ -1255,16 +1255,20 @@
 tory fac
+tory
  = newAp
@@ -1294,34 +1294,38 @@
 nfig);%0A        c
+ontex
 t
-x
 .setAttribute(Ra
@@ -1357,16 +1357,20 @@
 ORY, fac
+tory
 );%0A     
@@ -1368,24 +1368,30 @@
 y);%0A        
+final 
 ServletRackC
@@ -1459,18 +1459,22 @@
        c
+ontex
 t
-x
 .setAttr
@@ -1559,16 +1559,20 @@
      fac
+tory
 .init(ra
@@ -1593,16 +1593,25 @@
       %7D 
+%0A        
 catch (E
@@ -1620,17 +1620,16 @@
 eption e
-x
 ) %7B%0A    
@@ -1640,62 +1640,61 @@
     
-ctx.log(%22Error: application initialization failed%22, ex
+handleInitializationException(factory, rackContext, e
 );%0A 
@@ -1782,16 +1782,22 @@
         
+final 
 ServletC
@@ -1804,18 +1804,22 @@
 ontext c
+ontex
 t
-x
  = ctxEv
@@ -1883,16 +1883,20 @@
 tory fac
+tory
  =%0A     
@@ -1932,18 +1932,22 @@
 ctory) c
+ontex
 t
-x
 .getAttr
@@ -2000,16 +2000,20 @@
  if (fac
+tory
  != null
@@ -2031,16 +2031,20 @@
      fac
+tory
 .destroy
@@ -2052,34 +2052,38 @@
 );%0A            c
+ontex
 t
-x
 .removeAttribute
@@ -2129,18 +2129,22 @@
        c
+ontex
 t
-x
 .removeA
@@ -2444,19 +2444,283 @@
 y());%0A    %7D%0A
+ %0A    protected void handleInitializationException(%0A            final RackApplicationFactory factory,%0A            final ServletRackContext rackContext, %0A            final Exception e) %7B%0A        rackContext.log(%22Error: application initialization failed%22, e);%0A    %7D%0A
     %0A%7D%0A

introduce an overridable handleInitError for users unhappy about how initialization exceptions are swalowed (a compromise for #16)