/* 
 * Qlue Web Application Framework
 * Copyright 2009-2012 Ivan Ristic <ivanr@webkreator.com>
 *
 * Licensed 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 com.webkreator.qlue;

import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.SocketException;

/**
 * This class serves as a glue between Qlue applications and the Servlet
 * specification. It's an abstract class; a subclass should be used to create
 * the desired instance of the Qlue application.
 */
@MultipartConfig
public class QlueServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private static final String QLUE_APP_CLASS = "QLUE_APP_CLASS";

    private static final String QLUE_PAGES_ROOT_PACKAGE = "QLUE_PAGES_ROOT_PACKAGE";

    private QlueApplication qlueApp;

    /**
     * Retrieve servlet parameters from web.xml and initialize application.
     */
    @Override
    public final void init() throws ServletException {
        try {
            createApplicationObject();

            if (qlueApp == null) {
                throw new UnavailableException("QlueServlet: Application not available");
            }

            qlueApp.init(this);
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /**
     * By default, we look for a servlet init parameter to determine the name
     * of the application class. Subclasses can override this method to
     * obtain the application object in some other way.
     */
    protected void createApplicationObject() throws ClassNotFoundException {
        String pagesPackage = getServletConfig().getInitParameter(QLUE_PAGES_ROOT_PACKAGE);
        String appClassName = getServletConfig().getInitParameter(QLUE_APP_CLASS);

        if (pagesPackage != null) {
            if (appClassName != null) {
                throw new RuntimeException("Only one parameter allowed");
            }

            setApp(new QlueApplication(pagesPackage));
            return;
        }

        if (appClassName != null) {
            Class appClass = QlueApplication.classForName(appClassName);
            if (appClass == null) {
                throw new RuntimeException("Unable to find application class: " + appClassName);
            }

            if (!QlueApplication.class.isAssignableFrom(appClass)) {
                throw new RuntimeException("Application object not instance of QlueApplication: " + appClassName);
            }

            try {
                setApp((QlueApplication) appClass.newInstance());
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException("Unable to create application instance: " + appClassName);
            }
        }
    }

    /**
     * Associate Qlue application with this servlet.
     */
    protected void setApp(QlueApplication app) {
        this.qlueApp = app;
    }

    /**
     * Retrieve the application associated with this servlet.
     */
    protected QlueApplication getApp() {
        return qlueApp;
    }

    /**
     * This method is invoked by the servlet container, and all we do is pass on
     * the parameters to the associated Qlue application.
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            qlueApp.service(this, request, response);
        } catch (SocketException e) {
            // Ignore "Broken pipe" exceptions, which occur when clients go away.
            if ((e.getMessage() == null) || (!e.getMessage().contains("Broken pipe"))) {
                throw e;
            }
        }
    }

    /**
     * Invokes the destroy() method on the application object.
     */
    @Override
    public void destroy() {
        if (qlueApp == null) {
            return;
        }

        qlueApp.qlueBeforeDestroy();
        qlueApp.destroy();
    }
}

@@ -1524,24 +1524,114 @@
 ACKAGE%22;%0D%0A%0D%0A
+    private static final String QLUE_SERVLET_INIT_FAILED = %22QLUE_SERVLET_INIT_FAILED%22;%0D%0A%0D%0A
     private 
@@ -2083,32 +2083,235 @@
 Exception e) %7B%0D%0A
+            getServletContext().setAttribute(QLUE_SERVLET_INIT_FAILED, %22true%22);%0D%0A%0D%0A            if (e instanceof ServletException) %7B%0D%0A                throw (ServletException)e;%0D%0A            %7D else %7B%0D%0A    
             thro
@@ -2334,24 +2334,39 @@
 eption(e);%0D%0A
+            %7D%0D%0A
         %7D%0D%0A 

Set special flag on the servlet context if the server fails to initialize.