Package org.emrys.webosgi.core.runtime

Source Code of org.emrys.webosgi.core.runtime.BundledRequestDispatcher

package org.emrys.webosgi.core.runtime;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.emrys.webosgi.core.IFwkConstants;
import org.emrys.webosgi.core.internal.FwkRuntime;
import org.emrys.webosgi.core.jeewrappers.BundledHttpServletRequestWrapper;
import org.emrys.webosgi.core.jeewrappers.HttpServletResponseWrapper;
import org.emrys.webosgi.core.service.IOSGiWebContainer;

/**
* The Bundled Request Dispatcher.
*
* @author Leo Chang
* @version 2011-3-31
*/
public class BundledRequestDispatcher implements RequestDispatcher {
  private final String webCtxPath;
  private final IOSGiWebContainer webContainer;
  private String targetPath;
  private Object include_context_path;
  private Object include_servlet_path;
  private Object include_path_info;
  private Object include_request_uri;
  private Object include_query_string;
  private boolean doInternalFilter;

  public BundledRequestDispatcher(String wabCtxPath, String path) {
    this.webCtxPath = wabCtxPath;
    this.targetPath = path;
    webContainer = FwkRuntime.getInstance().getWebContainer();
  }

  public void forward(ServletRequest request, ServletResponse response)
      throws ServletException, IOException {
    if (response.isCommitted())
      throw new IllegalStateException(
          "This servlet response has been committed.");
    service(request, response, false);
  }

  public void include(ServletRequest request, ServletResponse response)
      throws ServletException, IOException {
    // Store these attribute in this request.
    /*
     * javax.servlet.include.context_path = ContextPath
     * javax.servlet.include.servlet_path = ServletPath
     * javax.servlet.include.path_info = PathInfo
     * javax.servlet.include.query_string = QueryString
     * javax.servlet.include.request_uri = RequestURI
     */
    service(request, response, true);
  }

  /**
   * Serve the reqeust, wiring back to the method. Forward and include on this
   * method, will not trigger the servlet filters.
   *
   * @param request
   * @param response
   * @param isInclude
   * @throws IOException
   * @throws ServletException
   */
  private void service(ServletRequest request, ServletResponse response,
      boolean isInclude) throws ServletException, IOException {
    BundledHttpServletRequestWrapper topRequest = (BundledHttpServletRequestWrapper) webContainer
        .getReqThreadVariants().get(OSGiWebContainer.THREAD_V_REQUEST);

    // Try to wrapper the given request and response.
    BundledHttpServletRequestWrapper reqWrapper = BundledHttpServletRequestWrapper
        .getHttpServletRequestWrapper(request, topRequest.getBundle());
    HttpServletResponseWrapper respWrapper = HttpServletResponseWrapper
        .getHttpServletResponseWrapper(response);

    // Buffer the former state and revert them at last.
    boolean oIsDispatched = reqWrapper.isDispatched();
    boolean oIsInclude = reqWrapper.isInclude();
    String oServletPath = reqWrapper.getServletPath();
    String oPathInfo = reqWrapper.getPathInfo();

    try {
      // Skip on system root path mark.
      if (targetPath.startsWith(IFwkConstants.SYS_PATH_PREFIX)) {
        targetPath = targetPath.substring(IFwkConstants.SYS_PATH_PREFIX
            .length());
      } else {
        if (!targetPath.startsWith("/")) {
          // Relative path not allowed, regard it as absolute.
          targetPath = "/" + targetPath;
        }

        if (this.webCtxPath != null && this.webCtxPath.length() != 0
            && !targetPath.startsWith("/" + this.webCtxPath + "/")) {
          targetPath = this.webCtxPath + targetPath;
        }
      }

      // Take the URI and query string together as targetURL, and later
      // set into request.
      String targetURL = targetPath;

      int index = targetPath.indexOf('?');
      if (index != -1) {
        String queryStr = targetPath.substring(index + 1);
        targetPath = targetPath.substring(0, index);
        reqWrapper.parseNewParameters(queryStr);
      }

      // set new path to dispatch to.
      reqWrapper.setServletPath(targetPath);
      // According to the tomcat's behavior, if forward, the request's URI
      // should be reset.
      if (!isInclude) {
        String oReqURL = reqWrapper.getRequestURL().toString();
        String ctxPath = reqWrapper.getContextPath();
        // Get the external top context path.
        int i = ctxPath.lastIndexOf('/');
        if (i > 0)
          ctxPath = ctxPath.substring(0, i);
        String newReqURI = ctxPath + targetPath;
        reqWrapper.setRequestURI(newReqURI);
        i = oReqURL.indexOf(ctxPath);
        if (i > -1) {
          String urlPrefix = oReqURL.substring(0, i
              + ctxPath.length());
          String newReqURL = urlPrefix + targetURL;
          reqWrapper.setRequestURL(newReqURL);
        }
      }

      reqWrapper.setPathInfo(null);

      // If need do filter, not set dispatching ad include mark.
      if (!doInternalFilter) {
        // If forward, we just reset the response's output buffer, not
        // reset the headers and status. So we invoke resetBuffer(), not
        // reset(); Notice, before dispatch this request, some filter or
        // servlet may add some cookie or set status. Tomcat remain them
        // after dispatch.
        if (!isInclude)
          respWrapper.resetBuffer(); // reset();
        // set the dispatching mark.
        reqWrapper.setDispatched(true);
        reqWrapper.setInclude(isInclude);
        // set include in response wrapper as well.
        respWrapper.setInclude(isInclude);

        // FIXME: If the original Request paths should not be modified
        // and just set several include_xxx attributes???
        if (isInclude && request instanceof HttpServletRequest) {
          // Store original include attribute.
          include_context_path = request
              .getAttribute("javax.servlet.include.context_path");
          include_servlet_path = request
              .getAttribute("javax.servlet.include.servlet_path");
          include_path_info = request
              .getAttribute("javax.servlet.include.path_info");
          include_request_uri = request
              .getAttribute("javax.servlet.include.request_uri");
          include_query_string = request
              .getAttribute("javax.servlet.include.query_string");

          request.setAttribute("javax.servlet.include.context_path",
              ((HttpServletRequest) request).getSession()
                  .getServletContext().getContextPath());
          request.setAttribute("javax.servlet.include.servlet_path",
              ((HttpServletRequest) request).getServletPath());
          request.setAttribute("javax.servlet.include.path_info",
              ((HttpServletRequest) request).getPathInfo());

          request.setAttribute("javax.servlet.include.request_uri",
              ((HttpServletRequest) request).getRequestURI());
          request.setAttribute("javax.servlet.include.query_string",
              ((HttpServletRequest) request).getQueryString());

        }
      }

      // rewire to JEE Container.
      webContainer.service(reqWrapper, respWrapper);
    } finally {
      // reset the include attributes at last.
      if (!doInternalFilter && isInclude
          && request instanceof HttpServletRequest) {
        // Store original include attribute.
        request.setAttribute("javax.servlet.include.context_path",
            include_context_path);
        request.setAttribute("javax.servlet.include.servlet_path",
            include_servlet_path);
        request.setAttribute("javax.servlet.include.path_info",
            include_path_info);
        request.setAttribute("javax.servlet.include.request_uri",
            include_request_uri);
        request.setAttribute("javax.servlet.include.query_string",
            include_query_string);
      }

      // revert the buffered state.
      reqWrapper.setServletPath(oServletPath);
      reqWrapper.setPathInfo(oPathInfo);
      reqWrapper.setDispatched(oIsDispatched);
      reqWrapper.setInclude(oIsInclude);
      respWrapper.setInclude(oIsInclude);
    }
  }

  public void setDoFilterInternal(boolean b) {
    doInternalFilter = b;
  }
}
TOP

Related Classes of org.emrys.webosgi.core.runtime.BundledRequestDispatcher

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.