@Override
  public NSArray getRequestHandlerPathForRequest(WORequest request) {
    NSMutableArray<Object> requestHandlerPath = new NSMutableArray<Object>();

    try {
      String path = request._uriDecomposed().requestHandlerPath();

      ERXRoute matchingRoute =
          setupRequestWithRouteForMethodAndPath(request, request.method(), path);
      if (matchingRoute != null) {
        @SuppressWarnings("unchecked")
        NSDictionary<ERXRoute.Key, String> keys =
            (NSDictionary<ERXRoute.Key, String>)
                request.userInfo().objectForKey(ERXRouteRequestHandler.KeysKey);
        String controller = keys.objectForKey(ERXRoute.ControllerKey);
        String actionName = keys.objectForKey(ERXRoute.ActionKey);
        requestHandlerPath.addObject(controller);
        requestHandlerPath.addObject(actionName);
      } else {
        requestHandlerPath.addObject(
            ERXProperties.stringForKeyWithDefault(
                "ERXRest.missingControllerName", "ERXMissingRouteController"));
        requestHandlerPath.addObject("missing");
        // throw new FileNotFoundException("There is no controller for the route '" + path + "'.");
      }

    } catch (Throwable t) {
      throw new RuntimeException("Failed to process the requested route.", t);
    }

    return requestHandlerPath;
  }
 @Override
 @SuppressWarnings("unchecked")
 public WOAction getActionInstance(Class class1, Class[] aclass, Object[] aobj) {
   ERXRouteController controller =
       (ERXRouteController) super.getActionInstance(class1, aclass, aobj);
   WORequest request = (WORequest) aobj[0];
   setupRouteControllerFromUserInfo(controller, request.userInfo());
   return controller;
 }
  /**
   * Sets up the request userInfo for the given request for a request of the given method and path.
   *
   * @param request the request to configure the userInfo on
   * @param method the request method
   * @param path the request path
   * @return the matching route for this method and path
   */
  public ERXRoute setupRequestWithRouteForMethodAndPath(
      WORequest request, String method, String path) {
    @SuppressWarnings("unchecked")
    NSDictionary<String, Object> userInfo = request.userInfo();
    NSMutableDictionary<String, Object> mutableUserInfo;
    if (userInfo instanceof NSMutableDictionary) {
      mutableUserInfo = (NSMutableDictionary<String, Object>) userInfo;
    } else if (userInfo != null) {
      mutableUserInfo = userInfo.mutableClone();
    } else {
      mutableUserInfo = new NSMutableDictionary<String, Object>();
    }

    ERXRoute matchingRoute = routeForMethodAndPath(method, path, mutableUserInfo);

    if (
    /*matchingRoute != null && */ mutableUserInfo != userInfo) {
      request.setUserInfo(mutableUserInfo);
    }

    return matchingRoute;
  }
  public WOResponse handleRequest(WORequest request) {
    WOResponse response = null;
    FileInputStream is = null;
    long length = 0;
    String contentType = null;
    String uri = request.uri();
    if (uri.charAt(0) == '/') {
      WOResourceManager rm = application.resourceManager();
      String documentRoot = documentRoot();
      File file = null;
      StringBuffer sb = new StringBuffer(documentRoot.length() + uri.length());
      String wodataKey = request.stringFormValueForKey("wodata");
      if (uri.startsWith("/cgi-bin") && wodataKey != null) {
        uri = wodataKey;
        if (uri.startsWith("file:")) {
          // remove file:/
          uri = uri.substring(5);
        } else {

        }
      } else {
        int index = uri.indexOf("/wodata=");

        if (index >= 0) {
          uri = uri.substring(index + "/wodata=".length());
        } else {
          sb.append(documentRoot);
        }
      }

      if (_useRequestHandlerPath) {
        try {
          WODynamicURL dynamicURL = new WODynamicURL(uri);
          String requestHandlerPath = dynamicURL.requestHandlerPath();
          if (requestHandlerPath == null || requestHandlerPath.length() == 0) {
            sb.append(uri);
          } else {
            sb.append("/");
            sb.append(requestHandlerPath);
          }
        } catch (Exception e) {
          throw new RuntimeException("Failed to parse URL '" + uri + "'.", e);
        }
      } else {
        sb.append(uri);
      }

      String path = sb.toString();
      try {
        path = path.replaceAll("\\?.*", "");
        if (request.userInfo() != null && !request.userInfo().containsKey("HttpServletRequest")) {
          /* PATH_INFO is already decoded by the servlet container */
          path = path.replace('+', ' ');
          path = URLDecoder.decode(path, CharEncoding.UTF_8);
        }
        file = new File(path);
        length = file.length();
        is = new FileInputStream(file);

        contentType = rm.contentTypeForResourceNamed(path);
        log.debug("Reading file '" + file + "' for uri: " + uri);
      } catch (IOException ex) {
        if (!uri.toLowerCase().endsWith("/favicon.ico")) {
          log.info("Unable to get contents of file '" + file + "' for uri: " + uri);
        }
      }
    } else {
      log.error("Can't fetch relative path: " + uri);
    }
    response = _generateResponseForInputStream(is, length, contentType);
    NSNotificationCenter.defaultCenter()
        .postNotification(WORequestHandler.DidHandleRequestNotification, response);
    response._finalizeInContext(null);
    return response;
  }