Package juzu.impl.bridge.spi.web

Source Code of juzu.impl.bridge.spi.web.Handler

/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package juzu.impl.bridge.spi.web;

import juzu.HttpMethod;
import juzu.Resource;
import juzu.impl.bridge.Bridge;
import juzu.impl.common.MethodHandle;
import juzu.impl.common.UriBuilder;
import juzu.impl.plugin.controller.ControllerService;
import juzu.impl.plugin.router.RouteDescriptor;
import juzu.impl.plugin.router.RouterDescriptor;
import juzu.impl.plugin.router.RouterService;
import juzu.impl.request.ControllerHandler;
import juzu.request.RequestParameter;
import juzu.impl.router.PathParam;
import juzu.impl.router.Route;
import juzu.impl.router.RouteMatch;
import juzu.impl.router.Router;
import juzu.request.Phase;

import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class Handler implements Closeable {

  /** . */
  private static final Phase[] GET_PHASES = {Phase.VIEW, Phase.ACTION, Phase.RESOURCE};

  /** . */
  private static final Phase[] POST_PHASES = {Phase.ACTION, Phase.VIEW, Phase.RESOURCE};

  /** . */
  private static final Phase[] OTHER_PHASES = {Phase.RESOURCE};

  /** . */
  final Bridge bridge;

  /** . */
  final Route root;

  /** . */
  final HashMap<MethodHandle, Route> forwardRoutes;

  /** . */
  final HashMap<Route, RouteDescriptor> backwardRoutes;

  public Handler(Bridge bridge) throws Exception {
    this.bridge = bridge;

    //
    HashMap<MethodHandle, Route> forwardRoutes = new HashMap<MethodHandle, Route>();
    HashMap<Route, RouteDescriptor> backwardRoutes = new HashMap<Route, RouteDescriptor>();

    //
    Route root = new Router();
    RouterService router = bridge.getApplication().resolveBean(RouterService.class);
    if (router != null) {
      RouterDescriptor desc = router.getDescriptor();
      if (desc != null) {
        Map<RouteDescriptor, Route> ret = desc.popupate(root);
        for (Map.Entry<RouteDescriptor, Route> entry : ret.entrySet()) {
          forwardRoutes.put(entry.getKey().handle, entry.getValue());
          backwardRoutes.put(entry.getValue(), entry.getKey());
        }
      }
    }

    //
    this.forwardRoutes = forwardRoutes;
    this.backwardRoutes = backwardRoutes;
    this.root = root;
  }

  public RouteDescriptor getMethods(Route route) {
    return backwardRoutes.get(route);
  }

  public Route getRoute(MethodHandle method) {
    return forwardRoutes.get(method);
  }

  public Route getRoot() {
    return root;
  }

  public Bridge getBridge() {
    return bridge;
  }

  public void handle(WebBridge bridge) throws Throwable {

    //
    String requestPath = bridge.getRequestContext().getRequestPath();

    // Determine first a possible match from the root route from the request path
    ControllerHandler requestTarget = null;
    RouteMatch requestMatch = null;
    Map<String, RequestParameter> requestParameters = Collections.emptyMap();
    if (requestPath.startsWith(bridge.getRequestContext().getPath())) {

      //
      HttpMethod requestMethod = bridge.getHttpContext().getMethod();
      Iterator<RouteMatch> matches = root.matcher(requestPath.substring(bridge.getRequestContext().getPath().length()), Collections.<String, String[]>emptyMap());

      // Determine a method
      while (matches.hasNext()) {
        RouteMatch match = matches.next();
        RouteDescriptor routeDesc = getMethods(match.getRoute());
        if (routeDesc != null) {
          ControllerHandler target = this.bridge.getApplication().resolveBean(ControllerService.class).getDescriptor().getMethodByHandle(routeDesc.handle);
          if (target.getPhase() == Phase.VIEW) {
            if (requestMethod == HttpMethod.POST) {
              requestTarget =  target;
              requestMatch = match;
            } else if (requestMethod == HttpMethod.GET) {
              requestTarget =  target;
              requestMatch = match;
              break;
            }
          } else if (target.getPhase() == Phase.ACTION) {
            if (requestMethod == HttpMethod.GET) {
              requestTarget =  target;
              requestMatch = match;
            } else if (requestMethod == HttpMethod.POST) {
              requestTarget =  target;
              requestMatch = match;
              break;
            }
          } else if (target.getPhase() == Phase.RESOURCE) {
            if (Arrays.asList(target.getMethod().getAnnotation(Resource.class).method()).contains(requestMethod)) {
              requestTarget =  target;
              requestMatch = match;
              break;
            }
          }
        }
      }

      // Determine parameters for the match
      if (requestMatch != null && (requestMatch.getMatched().size() > 0 || bridge.getRequestContext().getParameters().size() > 0)) {
        requestParameters = new HashMap<String, RequestParameter>();
        for (RequestParameter requestParameter : bridge.getRequestContext().getParameters().values()) {
          requestParameters.put(requestParameter.getName(), requestParameter);
        }
        for (Map.Entry<PathParam, String> entry : requestMatch.getMatched().entrySet()) {
          RequestParameter requestParameter = RequestParameter.create(entry.getKey().getName(), entry.getValue());
          requestParameters.put(requestParameter.getName(), requestParameter);
        }
      }
    }

    // No method means we either send a server resource
    // or we look for the handler method
    if (requestTarget == null) {
      // If we have an handler we locate the index method
      requestTarget = this.bridge.getApplication().resolveBean(ControllerService.class).getResolver().resolve(Phase.VIEW, Collections.<String>emptySet());
    }

    // No method -> not found
    if (requestTarget == null) {
      bridge.getRequestContext().setStatus(404);
    } else {
      if (requestMatch == null) {
        Route requestRoute = getRoute(requestTarget.getHandle());
        if (requestRoute != null) {
          requestMatch = requestRoute.matches(Collections.<String, String>emptyMap());
          if (requestMatch != null) {
            StringBuilder sb = new StringBuilder();
            requestMatch.render(new UriBuilder(sb));
            if (!sb.toString().equals(requestPath)) {
              StringBuilder redirect = new StringBuilder();
              bridge.renderRequestURL(redirect);
              redirect.append(sb);
              bridge.getRequestContext().sendRedirect(redirect.toString());
              return;
            }
          }
        }
      }

      //
      WebRequestBridge requestBridge;
      if (requestTarget.getPhase() == Phase.ACTION) {
        requestBridge = new WebActionBridge(this.bridge, this, bridge, requestTarget, requestParameters);
      } else if (requestTarget.getPhase() == Phase.VIEW) {
        requestBridge = new WebViewBridge(this.bridge, this, bridge, requestTarget, requestParameters);
      } else if (requestTarget.getPhase() == Phase.RESOURCE) {
        requestBridge = new WebResourceBridge(this.bridge, this, bridge, requestTarget, requestParameters);
      } else {
        throw new Exception("Cannot decode phase");
      }

      //
      requestBridge.invoke();

      //
      if (requestBridge.send()) {
        // ok
      } else {
        throw new UnsupportedOperationException("Not yet handled by " + requestBridge.getClass().getSimpleName() + ": " + requestBridge.response);
      }
    }
  }

  public void close() throws IOException {
  }
}
TOP

Related Classes of juzu.impl.bridge.spi.web.Handler

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.