Package ch.entwine.weblounge.kernel.site

Source Code of ch.entwine.weblounge.kernel.site.Precompiler

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program 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.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.kernel.site;

import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import ch.entwine.weblounge.common.content.Renderer.RendererType;
import ch.entwine.weblounge.common.content.page.Page;
import ch.entwine.weblounge.common.content.page.PageTemplate;
import ch.entwine.weblounge.common.content.page.Pagelet;
import ch.entwine.weblounge.common.content.page.PageletRenderer;
import ch.entwine.weblounge.common.content.page.PageletURI;
import ch.entwine.weblounge.common.impl.content.page.MockPageImpl;
import ch.entwine.weblounge.common.impl.content.page.PageletImpl;
import ch.entwine.weblounge.common.impl.content.page.PageletURIImpl;
import ch.entwine.weblounge.common.impl.security.Guest;
import ch.entwine.weblounge.common.impl.site.PrecompileHttpServletRequest;
import ch.entwine.weblounge.common.impl.testing.MockHttpServletResponse;
import ch.entwine.weblounge.common.request.WebloungeRequest;
import ch.entwine.weblounge.common.security.SecurityService;
import ch.entwine.weblounge.common.site.Environment;
import ch.entwine.weblounge.common.site.Module;
import ch.entwine.weblounge.common.site.Site;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

/**
* This precompiler searches an OSGi bundle for Java Server Pages (JSP) and
* sends a request to <code>JspC</code>, the java server page compiler provided
* by Jasper in order to get the compilation work done before a user request
* hits the jsp.
*/
public class Precompiler {

  /** Logging facility */
  protected static final Logger logger = LoggerFactory.getLogger(SiteDispatcherServiceImpl.class);

  /** The site servlet */
  protected SiteServlet servlet = null;

  /** The worker */
  protected PrecompileWorker worker = null;

  /** Flag to indicate whether to keep working or not */
  protected boolean keepGoing = true;

  /** Running flag */
  protected boolean isRunning = true;

  /** Switch for precompiler error logging */
  protected boolean logErrors = true;

  /** The default environment */
  protected Environment environment = Environment.Any;

  /** The security service */
  protected SecurityService security = null;

  /** The key used to identify this compilation process */
  protected String compilerKey = null;

  /**
   * Creates a new precompiler for the site identified by the servlet.
   *
   * @param key
   *          the compiler key
   * @param servlet
   *          the site servlet
   * @param environment
   *          the environment to use
   * @param security
   *          the security service
   * @param logErrors
   *          <code>true</code> to log precompilation errors
   */
  public Precompiler(String key, SiteServlet servlet, Environment environment,
      SecurityService security, boolean logErrors) {
    this.compilerKey = key;
    this.servlet = servlet;
    this.environment = environment;
    this.security = security;
    this.logErrors = logErrors;
  }

  /**
   * Precompiles all of the bundle's server pages intoto the output directory as
   * specified in the <code>scratchDir</code> setting of the compiler
   * configuration.
   *
   * @param outputDir
   *          the path to the output directory
   */
  public void precompile() {
    worker = new PrecompileWorker(servlet);
    Thread workerThread = new Thread(worker);
    workerThread.setPriority(Thread.MIN_PRIORITY);
    workerThread.setDaemon(true);
    workerThread.start();
  }

  /**
   * Returns <code>true</code> if the precompiler is still running.
   *
   * @return <code>true</code> if the compiler is still running
   */
  public boolean isRunning() {
    return isRunning;
  }

  /**
   * Returns the key that is used to identify this compilation process.
   *
   * @return the compiler key
   */
  public String getCompilerKey() {
    return compilerKey;
  }

  /**
   * Stops the current precompilation work.
   */
  public void stop() {
    logger.debug("Asking precompiler for '{}' to stop", servlet.getSite());
    keepGoing = false;
  }

  class PrecompileWorker implements Runnable {

    /** The servlet to use */
    private SiteServlet servlet = null;

    /**
     * Creates a new jsp precompilation worker.
     *
     * @param servlet
     *          the servlet
     */
    public PrecompileWorker(SiteServlet servlet) {
      this.servlet = servlet;
    }

    /**
     * {@inheritDoc}
     *
     * @see java.lang.Runnable#run()
     */
    public void run() {

      Site site = servlet.getSite();

      // Prepare the mock request and response objects
      PrecompileHttpServletRequest request = new PrecompileHttpServletRequest();
      request.setServerName(site.getHostname(environment).getURL().getHost());
      request.setServerPort(site.getHostname(environment).getURL().getPort());
      request.setMethod(site.getHostname(environment).getURL().getProtocol());
      request.setServletPath("");

      // Prepare a fake page in order to prevent erratic behavior during
      // precompilation
      Page page = new MockPageImpl(site);
      Pagelet pagelet = null;
      for (Module m : site.getModules()) {
        if (m.getRenderers().length > 0) {
          PageletRenderer r = m.getRenderers()[0];
          PageletURI pageletURI = new PageletURIImpl(page.getURI(), PageTemplate.DEFAULT_STAGE, 0);
          pagelet = new PageletImpl(pageletURI, m.getIdentifier(), r.getIdentifier());
        }
      }

      // Collect all renderers from modules and ask for precompilation
      List<URL> rendererUrls = new ArrayList<URL>();
      for (Module m : site.getModules()) {
        if (!m.isEnabled())
          break;
        for (PageletRenderer p : m.getRenderers()) {
          if (p.getRenderer() != null)
            rendererUrls.add(p.getRenderer());
          if (p.getRenderer(RendererType.Feed.name()) != null)
            rendererUrls.add(p.getRenderer(RendererType.Feed.name()));
          if (p.getRenderer(RendererType.Search.name()) != null)
            rendererUrls.add(p.getRenderer(RendererType.Search.name()));
          if (p.getEditor() != null)
            rendererUrls.add(p.getEditor());
        }
      }

      // Collect all site templates and ask for precompilation
      for (PageTemplate t : site.getTemplates()) {
        if (t.getRenderer() != null)
          rendererUrls.add(t.getRenderer());
      }

      if (rendererUrls.size() < 1) {
        logger.debug("No java server pages found to precompile for {}", site);
        return;
      }

      // Make sure there is a user
      security.setUser(new Guest(site.getIdentifier()));
      security.setSite(site);

      logger.info("Precompiling java server pages for '{}'", site);
      int errorCount = 0;
      Iterator<URL> rendererIterator = rendererUrls.iterator();
      while (keepGoing && rendererIterator.hasNext()) {
        MockHttpServletResponse response = new MockHttpServletResponse();
        URL entry = rendererIterator.next();
        String path = entry.getPath();
        String pathInfo = path.substring(path.indexOf(site.getIdentifier()) + site.getIdentifier().length());
        request.setPathInfo(pathInfo);
        request.setRequestURI(pathInfo);
        request.setAttribute(WebloungeRequest.PAGE, page);
        request.setAttribute(WebloungeRequest.COMPOSER, page.getComposer(PageTemplate.DEFAULT_STAGE));
        if (pagelet != null)
          request.setAttribute(WebloungeRequest.PAGELET, pagelet);

        try {
          logger.debug("Precompiling {}:/{}", site, pathInfo);
          servlet.service(request, response);
          switch (response.getStatus()) {
            case HttpServletResponse.SC_OK:
              logger.debug("Precompilation of {}:/{} finished", site, pathInfo);
              break;
            case SC_NOT_FOUND:
              logger.error("Precompilation failed: {}:/{}: not found", site, pathInfo);
              break;
            default:
              logger.debug("Precompilation of {}:/{} failed with status {}", new Object[] {
                  site,
                  pathInfo,
                  response.getStatus() });
              break;
          }
        } catch (Throwable t) {
          while (t != t.getCause() && t.getCause() != null)
            t = t.getCause();
          if (logErrors)
            logger.warn("Error precompiling {}:/{}: {}", new Object[] {
                site,
                pathInfo,
                t.getMessage() });
          errorCount++;
        }
      }

      isRunning = false;

      security.setUser(null);
      security.setSite(null);

      // Log the precompilation results
      if (!keepGoing) {
        logger.info("Precompilation for '{}' canceled", site);
      } else if (errorCount > 0) {
        String compilationResult = "finished";
        compilationResult += " with " + errorCount + " errors";
        logger.warn("Precompilation for '{}' {}", site, compilationResult);
        if (!logErrors)
          logger.info("Precompilation error logging can be enabled in the site dispatcher service");
      } else {
        logger.info("Precompilation for '{}' finished", site);
      }
    }
  }

}
TOP

Related Classes of ch.entwine.weblounge.kernel.site.Precompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.