Package org.richfaces.test

Source Code of org.richfaces.test.AbstractFacesTest

/**
*
*/
package org.richfaces.test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.EventListener;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.LogManager;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.render.RenderKitFactory;
import javax.faces.webapp.FacesServlet;
import javax.servlet.Filter;

import junit.framework.TestCase;

import org.junit.After;
import org.junit.Before;
import org.richfaces.test.staging.FilterContainer;
import org.richfaces.test.staging.ServletContainer;
import org.richfaces.test.staging.StagingConnection;
import org.richfaces.test.staging.StagingServer;

/**
* Base class for all JSF test cases.
* @author asmirnov
*
*/
public abstract class AbstractFacesTest extends TestCase {

  private ClassLoader contextClassLoader;

  /**
   * Prepared test server instance. Populated by the default {@link #setUp()} method.
   */
  protected StagingServer facesServer;

  /**
   * Current virtual connection. This field populated by the {@link #setupWebContent()} method only.
   */
  protected StagingConnection connection;

  /**
   * Current {@link FacesContext} instance. This field populated by the {@link #setupWebContent()} method only.
   */
  protected FacesContext facesContext;

  /**
   * JSF {@link Lifecycle} instance. Populated by the default {@link #setUp()} method.
   */
  protected Lifecycle lifecycle;

  /**
   * JSF {@link Application} instance. Populated by the default {@link #setUp()} method.
   */
  protected Application application;

  /**
   * Setup staging server instance with JSF implementation. First, this method creates a local test instance
   * and calls the other template method in the next sequence:
   * <ol>
   * <li>{@link #setupFacesServlet()}</li>
   * <li>{@link #setupFacesListener()}</li>
   * <li>{@link #setupJsfInitParameters()}</li>
   * <li>{@link #setupWebContent()}</li>
   * </ol>
   * After them, test server is initialized as well as fields {@link #lifecycle} and {@link #application} populated.
   * Also, if the resource "logging.properties" is exist in the test class package, The Java {@link LogManager} will be configured with its content. 
   * @throws java.lang.Exception
   */
  @Before
  public void setUp() throws Exception {
    contextClassLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(
        this.getClass().getClassLoader());
    InputStream stream = this.getClass().getResourceAsStream(
        "logging.properties");
    if (null != stream) {
      try {
        LogManager.getLogManager().readConfiguration(stream);
      } catch (Exception e) {
        // Ignore it.
      } finally {
        try {
          stream.close();
        } catch (IOException e) {
          // Ignore it.
        }
      }
    }
    facesServer = new StagingServer();
    setupFacesServlet();
    setupFacesListener();
    setupJsfInitParameters();
    setupWebContent();
    facesServer.init();
    ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
        .getFactory(FactoryFinder.APPLICATION_FACTORY);
    application = applicationFactory.getApplication();
    LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
        .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
    lifecycle = lifecycleFactory
        .getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
  }

  /**
   * This hook method called from the {@link #setUp()} should append JSF implementation
   * listener to the test server. Default version applends "com.sun.faces.config.ConfigureListener"
   * or "org.apache.myfaces.webapp.StartupServletContextListener" for the existed SUN RI or MyFaces implementation.
   * This metod also calls appropriate {@link #setupSunFaces()} or {@link #setupMyFaces()} methods.
   */
  protected void setupFacesListener() {
    EventListener listener = null;
    try {
      // Check Sun RI configuration listener class.
      Class<? extends EventListener> listenerClass = contextClassLoader
          .loadClass("com.sun.faces.config.ConfigureListener")
          .asSubclass(EventListener.class);
      listener = listenerClass.newInstance();
      setupSunFaces();
    } catch (ClassNotFoundException e) {
      // No JSF RI listener, check MyFaces.
      Class<? extends EventListener> listenerClass;
      try {
        listenerClass = contextClassLoader
            .loadClass(
                "org.apache.myfaces.webapp.StartupServletContextListener")
            .asSubclass(EventListener.class);
        listener = listenerClass.newInstance();
        setupMyFaces();
      } catch (ClassNotFoundException e1) {
        throw new TestException("No JSF listeners have been found", e1);
      } catch (Exception e2) {
        throw new TestException("Error instantiate MyFaces listener",
            e2);
      }
    } catch (Exception e) {
      throw new TestException("Error instantiate JSF RI listener", e);
    }
    facesServer.addWebListener(listener);
  }

  /**
   * This template method called from {@link #setUp()} to create {@link FacesServlet} instance.
   * The default implementation also tests presense of the "org.ajax4jsf.Filter" class.
   * If this class is avalable, these instance appended to the Faces Servlet call chain.
   * Default mapping to the FacesServlet instance is "*.jsf"
   */
  protected void setupFacesServlet() {
    ServletContainer facesServletContainer = new ServletContainer("*.jsf",
        new FacesServlet());
    facesServletContainer.setName("Faces Servlet");
    try {
      // Check for an ajax4jsf filter.
      Class<? extends Filter> ajaxFilterClass = contextClassLoader
          .loadClass("org.ajax4jsf.Filter").asSubclass(Filter.class);
      Filter ajaxFilter = ajaxFilterClass.newInstance();
      FilterContainer filterContainer = new FilterContainer(ajaxFilter,
          facesServletContainer);
      filterContainer.setName("ajax4jsf");
      facesServer.addResource("/WEB-INF/web.xml",
          "org/richfaces/test/ajax-web.xml");
      facesServer.addServlet(filterContainer);
    } catch (ClassNotFoundException e) {
      // No Richfaces filter, uses servlet directly.
      facesServer.addResource("/WEB-INF/web.xml",
          "org/richfaces/test/web.xml");
      facesServer.addServlet(facesServletContainer);
    } catch (Exception e) {
      throw new TestException(e);
    }
  }

  /**
   * This template method called from {@link #setUp()} to append appropriate init parameters to the test server.
   * The default implementation sets state saving method to the "server" and default jsf page suffix to the ".xhtml"
   */
  protected void setupJsfInitParameters() {
    facesServer.addInitParameter(
        StateManager.STATE_SAVING_METHOD_PARAM_NAME,
        StateManager.STATE_SAVING_METHOD_SERVER);
    facesServer.addInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME,
        ".xhtml");
  }

  /**
   * This template method called from the {@link #setupFacesListener()} if MyFaces implementation presents.
   * The default implementation does nothing.
   */
  protected void setupMyFaces() {
    // Do nothing by default.
  }

  /**
   * This template method called from the {@link #setupFacesListener()} if Sun JSF reference implementation presents.
   * The default implementation sets the "com.sun.faces.validateXml" "com.sun.faces.verifyObjects" init parameters to the "true"
   */
  protected void setupSunFaces() {
    facesServer.addInitParameter("com.sun.faces.validateXml", "true");
    facesServer.addInitParameter("com.sun.faces.verifyObjects", "true");
  }

  /**
   * This template method called from the {@link #setUp()} to populate virtual server content.
   * The default implementation tries to load web content from directory pointed by the System property
   * "webroot" or same property from the "/webapp.properties" file.
   */
  protected void setupWebContent() {
    String webappDirectory = System.getProperty("webroot");
        File webFile = null;
        if (null == webappDirectory) {
                URL resource = this.getClass().getResource("/webapp.properties");
                if (null != resource && "file".equals(resource.getProtocol())) {
                  Properties webProperties = new Properties();
                  try {
            InputStream inputStream = resource.openStream();
            webProperties.load(inputStream);
            inputStream.close();
                      webFile = new File(resource.getPath());
                      webFile = new File(webFile.getParentFile(), webProperties.getProperty("webroot")).getAbsoluteFile();
                  facesServer.addResourcesFromDirectory("/", webFile);
          } catch (IOException e) {
            throw new TestException(e);
          }
                }
        } else {
                webFile = new File(webappDirectory);
            facesServer.addResourcesFromDirectory("/", webFile);
        }

  }

  /**
   * Setup virtual server connection to run tests inside JSF lifecycle.
   * The default implementation setups virtual request to the "http://localhost/test.jsf" URL and creates {@link FacesContext} instance.
   * Two template methods are called :
   * <ol>
   * <li>{@link #setupConnection()} to prepare request method, parameters, headers and so</li>
   * <li>{@link #setupView()} to create default view.</li>
   * </ol>
   * @throws Exception
   */
  protected void setupFacesRequest() throws Exception {
    String url = "http://localhost/test.jsf";
    setupFacesRequest(url);
    UIViewRoot viewRoot = setupView();
    if (null != viewRoot) {
      facesContext.setViewRoot(viewRoot);
    }
  }

  /**
   * <p class="changed_added_2_0"></p>
   * @param url
   * @throws MalformedURLException
   * @throws FacesException
   */
  protected void setupFacesRequest(String url) throws MalformedURLException,
      FacesException {
    connection = facesServer.getConnection(new URL(
        url));
    setupConnection();
    connection.start();
    FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
        .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
    facesContext = facesContextFactory.getFacesContext(facesServer
        .getContext(), connection.getRequest(), connection
        .getResponse(), lifecycle);
  }

  /**
   * This template method called from the {@link #setupFacesRequest()} to create components view tree in the virtual request.
   * The default implementation is only creates {@link UIViewRoot} instance for view ID "/test.xhtml".
   * @return
   */
  protected UIViewRoot setupView() {
    UIViewRoot viewRoot = (UIViewRoot) application.createComponent(UIViewRoot.COMPONENT_TYPE);
    viewRoot.setViewId("/test.xhtml");
    viewRoot.setLocale(Locale.getDefault());
    viewRoot.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
    return viewRoot;
  }

  /**
   * This template method called from the {@link #setupFacesRequest()} to setup additional virtual connection parameters.
   * The default implementation does nothing.
   */
  protected void setupConnection() {

  }

  /**
   * Virtual server instance cleanup.
   * @throws java.lang.Exception
   */
  @After
  public void tearDown() throws Exception {
    if (null != facesContext) {
      facesContext.release();
      facesContext = null;
    }
    if (null != connection) {
      if (!connection.isFinished()) {
        connection.finish();
      }
      connection = null;
    }
    facesServer.destroy();
    Thread.currentThread().setContextClassLoader(contextClassLoader);
    facesServer = null;
    application = null;
    lifecycle = null;
  }

}
TOP

Related Classes of org.richfaces.test.AbstractFacesTest

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.