org.nuxeo.ecm.webengine.servlet.WebServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.nuxeo.ecm.webengine.servlet.WebServlet.java

Source

/*
 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     Nuxeo - initial API and implementation
 *
 * $Id$
 */

package org.nuxeo.ecm.webengine.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.utils.Path;
import org.nuxeo.ecm.webengine.DefaultWebContext;
import org.nuxeo.ecm.webengine.PathInfo;
import org.nuxeo.ecm.webengine.RequestHandler;
import org.nuxeo.ecm.webengine.WebApplication;
import org.nuxeo.ecm.webengine.WebContext;
import org.nuxeo.ecm.webengine.WebEngine;
import org.nuxeo.ecm.webengine.WebException;
import org.nuxeo.ecm.webengine.WebObject;
import org.nuxeo.ecm.webengine.scripting.ScriptFile;
import org.nuxeo.runtime.api.Framework;

/**
 * Servlet for publishing SiteObjects
 *
 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a>
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 *
 */
public class WebServlet extends HttpServlet {

    protected static final int BUFFER_SIZE = 4096 * 16;

    private static final long serialVersionUID = 965764764858L;

    private static final Log log = LogFactory.getLog(WebServlet.class);

    private static final ThreadLocal<WebContext> CONTEXT = new ThreadLocal<WebContext>();

    private WebEngine engine;

    public final static WebContext getContext() {
        return CONTEXT.get();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        engine = Framework.getLocalService(WebEngine.class);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //double start = System.currentTimeMillis();
        resp.setContentType("text/html");
        if (req.getMethod().equals(WebConst.METHOD_HEAD)) {
            resp = new NoBodyResponse(resp);
        }

        WebContext context = null;
        try {
            // create the request context
            context = engine.createContext(req, resp);
            context.initialize();
            CONTEXT.set(context);
            service(context, req, resp);
        } catch (Throwable e) {
            WebException we = WebException.wrap(e);
            log.error("Site Servlet failed to handle request", e);
            if (context == null) {
                WebApplication app = engine.getDefaultApplication();
                if (app == null) {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    PrintStream buf = new PrintStream(baos);
                    buf.print("Failed to create request context. "
                            + "<p>Cannot create pretty error message since a default application is not defined."
                            + "<p>Error message is: " + e.getMessage() + "<p>The stack trace is:<hr><p><pre>");
                    e.printStackTrace(buf);
                    buf.print("</pre>");
                    buf.close();
                    resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, new String(baos.toByteArray()));
                    return;
                }
                String p = req.getPathInfo();
                context = new DefaultWebContext(app, new PathInfo(p == null ? PathInfo.ROOT_PATH : new Path(p)),
                        req, resp);
            }
            WebApplication app = context.getApplication();
            ScriptFile page = context.getFile(app.getErrorPage());
            if (page == null) {
                displayError(resp, we, "ErrorPage not found: " + app.getErrorPage(),
                        WebConst.SC_INTERNAL_SERVER_ERROR);
                return;
            }
            try {
                context.setProperty("error", we);
                context.exec(page, null);
            } catch (Throwable ee) {
                displayError(resp, ee, "Failed to show error page", WebConst.SC_INTERNAL_SERVER_ERROR);
            }
        } finally {
            CONTEXT.set(null);
        }
        //System.out.println(">>> SITE REQUEST TOOK:  "+((System.currentTimeMillis()-start)/1000));
    }

    protected void service(WebContext context, HttpServletRequest req, HttpServletResponse resp) throws Exception {
        if (context.getLastObject() == null) { // a request outside the root
            showStaticPage(context);
            return;
        }

        String method = req.getMethod();
        WebObject targetObject = context.getTargetObject();
        if (targetObject == null) {
            showStaticPage(context);
            return;
        }
        // avoid running default action handling mechanism when invocation is redirected to scripts
        if (context.getPathInfo().getScript() == null) {
            RequestHandler handler = targetObject.getRequestHandler();
            if (handler != null) {
                if (method.equals(WebConst.METHOD_POST)) {
                    handler.doPost(targetObject);
                } else if (method.equals(WebConst.METHOD_PUT)) {
                    handler.doPut(targetObject);
                } else if (method.equals(WebConst.METHOD_GET)) {
                    handler.doGet(targetObject);
                } else if (method.equals(WebConst.METHOD_DELETE)) {
                    handler.doDelete(targetObject);
                } else if (method.equals(WebConst.METHOD_HEAD)) {
                    handler.doHead(targetObject);
                }
            }
        }

        // return is handler has done the rendering
        if (context.isCanceled()) {
            return;
        }

        //double s = System.currentTimeMillis();
        ScriptFile script = context.getTargetScript();
        if (script != null) {
            context.exec(script, null);
        } else {
            context.getResponse().setStatus(WebConst.SC_NOT_FOUND);
        }
        //System.out.println(">>>>>>>>>> RENDERING TOOK: " + ((System.currentTimeMillis() - s) / 1000));
    }

    protected static void displayError(HttpServletResponse resp, Throwable t, String message, int code) {
        PrintWriter writer;
        try {
            writer = resp.getWriter();
        } catch (IOException e) {
            log.error("Unable to output Error ", e);
            log.error("Application error was " + message, e);
            return;
        }

        writer.write("\nError occured during Site rendering");
        writer.write("\nSite Error message : " + message);
        if (t != null) {
            writer.write("\nException message : " + t.getMessage());
            for (StackTraceElement element : t.getStackTrace()) {
                writer.write("\n" + element.toString());
            }
        }

        resp.setStatus(code);
    }

    protected void displayError(HttpServletResponse resp, Throwable t, String message) {
        if (t instanceof WebException) {
            WebException st = (WebException) t;
            displayError(resp, t, message, st.getReturnCode());
        } else {
            displayError(resp, t, message, WebConst.SC_INTERNAL_SERVER_ERROR);
        }
    }

    public void showStaticPage(WebContext context) throws Exception {
        try {
            //double s = System.currentTimeMillis();
            ScriptFile script = context.getTargetScript();
            if (script != null) {
                context.exec(script, null);
            } else {
                context.getResponse().sendError(WebConst.SC_NOT_FOUND);
            }
            //System.out.println(">>>>>>>>>> STATIC RENDERING TOOK: "+ ((System.currentTimeMillis() - s)/1000));
        } catch (WebException e) {
            displayError(context.getResponse(), e, "Error during the rendering process");
        }
    }

    @Override
    public void destroy() {
        DefaultWebContext.destroyAnonymousSession();
    }

}