Package org.emrys.webosgi.core.handlers

Source Code of org.emrys.webosgi.core.handlers.CustomizeServletHandler

/**
*
*/
package org.emrys.webosgi.core.handlers;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.emrys.webosgi.core.jeeres.ClonedExecutableServletObject;
import org.emrys.webosgi.core.jeeres.FilterDelegate;
import org.emrys.webosgi.core.jeeres.ServletDelegate;
import org.emrys.webosgi.core.jeewrappers.BundledHttpServletRequestWrapper;
import org.emrys.webosgi.core.jeewrappers.HttpServletResponseWrapper;
import org.emrys.webosgi.core.runtime.OSGiWebContainer;
import org.osgi.framework.Bundle;


/**
* @author LeoChang
*
*/
public class CustomizeServletHandler extends AbstractFwkReqeustHandler
    implements IFwkRequestHandler {

  public static final int PRIORITY = 200;

  public CustomizeServletHandler(OSGiWebContainer fwkContainer) {
    super(fwkContainer);
  }

  public void handle(BundledHttpServletRequestWrapper request,
      HttpServletResponseWrapper response, IFwkHandlerChain handlerChain)
      throws IOException, ServletException {
    // Record the old path before servlet invoke, and reset to the req at
    // last. Otherwise, the filter will not be matched to the modified path.
    BundledHttpServletRequestWrapper topRequest = request.getTopWrapper();
    // HttpServletResponseWrapper topResponse = response.getTopWrapper();
    String oldPathInfo = topRequest.getPathInfo();
    String oldServletPath = topRequest.getServletPath();

    try {
      // Because a servlet may have mutiple url pattern map. Here
      // create mutiple cloned copy of a servlet for each url
      // parttern. And then, sort these copys of many servlets
      // according to some regular into a wait queue. If one copy be
      // executed, others of the same servlet or filter won't execute.
      Collection<FilterDelegate> filters = getFwkContainerHelper()
          .getAllBufferedFilters(false);
      List<ClonedExecutableServletObject<ServletDelegate>> servletCopys = getFwkContainerHelper()
          .sortURLPatternsExeObjs(ServletDelegate.class, false);

      // Try to find the url matched servlet copy below.
      ClonedExecutableServletObject<ServletDelegate> servletDelegateCopy = null;
      try {
        servletDelegateCopy = getFwkContainerHelper()
            .chooseDelegateServlet(request, servletCopys);
      } catch (Exception e) {
        throw new ServletException(e);
      }

      if (servletDelegateCopy != null) {
        ServletDelegate servletDelegate = servletDelegateCopy
            .getOriginalObj();
        Object oldBundle = topRequest.getBundle();
        // Only need to set once, because the filter of same bundle
        // with the servlet can be called.
        getFwkContainerHelper().switchReqBundleContext(
            servletDelegate.getBundleContext().getBundle());
        try {
          doServletMapFilter(servletDelegate, request, response,
              filters);
        } finally {
          // Revert bundle of Top Req
          getFwkContainerHelper().switchReqBundleContext(
              (Bundle) oldBundle);
        }
      } else {
        // No matched servlet found, set NOT_FOUND status rather than
        // throw ServletException.
        /*throw new ServletException("No Service found for Request URI:"
            + request.getRequestURI());*/
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
      }
    } finally {
      // Reset the pathinfo and servlet path to the buffered request.
      // Because serlvet mapping will modify these two variants, and then
      // the web bundle's flters will not be maped after the servlet
      // invoked.
      topRequest.setPathInfo(oldPathInfo);
      topRequest.setServletPath(oldServletPath);
    }
  }

  /**
   * Do servlet mapped filter before the target servlet be invoked.
   *
   * @param delegate
   * @param request
   * @param response
   * @param filters
   * @throws IOException
   * @throws ServletException
   */
  private void doServletMapFilter(final ServletDelegate delegate,
      final BundledHttpServletRequestWrapper request,
      HttpServletResponseWrapper response,
      Collection<FilterDelegate> filters) throws IOException,
      ServletException {

    final String servletName = delegate.name;
    final Iterator<FilterDelegate> it = filters.iterator();

    final FilterChain chain = new FilterChain() {

      public void doFilter(final ServletRequest request,
          final ServletResponse response) throws IOException,
          ServletException {
        if (!it.hasNext()) {
          delegate.service(request, response);
          return;
        }

        FilterDelegate i = it.next();
        while (i != null
            && !(i.isSameBundled(delegate)
                && i.targetServletNames != null && (checkMatched(
                i, servletName) || checkMatched(i,
                delegate.className)))) {
          if (it.hasNext())
            i = it.next();
          else {
            i = null;
          }
        }
        if (i != null) {
          i.doFilter(request, response, this);
        } else if (!it.hasNext()) {
          delegate.service(request, response);
        }
      }

      private boolean checkMatched(FilterDelegate i, String tarServletName) {
        if (StringUtils.isEmpty(tarServletName))
          return false;

        boolean isDispatched = request.isDispatched();
        String tarServletMapStr = i.targetServletNames;
        // If servlet map not contains dispatchers config, do simple
        // check. Only when REQUEST req allowed.
        if (tarServletMapStr
            .indexOf(FilterDelegate.DISPATCHERS_PARTTERN_SEPERATOR) == -1)
          return !isDispatched
              && tarServletMapStr.contains(tarServletName);

        boolean isIncluded = request.isInclude();
        String[] tarServletMapSegs = tarServletMapStr
            .split(FilterDelegate.MULTI_MAP_SEG_SEPERATOR);
        for (String seg : tarServletMapSegs) {
          int index = seg
              .indexOf(FilterDelegate.DISPATCHERS_PARTTERN_SEPERATOR);
          if (index == -1 && !isDispatched
              && seg.contains(tarServletName))
            return true;

          if (index > -1) {
            if (seg.contains(tarServletName)) {
              String dispatchers = seg.substring(0, index);
              if (!isDispatched
                  && dispatchers
                      .contains(FilterDelegate.DISPATCHERS.REQUEST
                          .name()))
                return true;
              if (isDispatched
                  && !isIncluded
                  && dispatchers
                      .contains(FilterDelegate.DISPATCHERS.FORWARD
                          .name()))
                return true;
              if (isDispatched
                  && isIncluded
                  && dispatchers
                      .contains(FilterDelegate.DISPATCHERS.INCLUDE
                          .name()))
                return true;
            }
          }
        }
        return false;
      }
    };

    chain.doFilter(request, response);
  }

  @Override
  public int getPriority() {
    return PRIORITY;
  }
}
TOP

Related Classes of org.emrys.webosgi.core.handlers.CustomizeServletHandler

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.