Package org.mojavemvc.core

Source Code of org.mojavemvc.core.HttpActionInvoker

/*
* Copyright (C) 2011-2013 Mojavemvc.org
*
* 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 org.mojavemvc.core;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.cglib.reflect.FastClass;

import org.mojavemvc.aop.RequestContext;
import org.mojavemvc.views.EmptyView;
import org.mojavemvc.views.View;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Injector;

/**
* @author Luis Antunes
*/
public class HttpActionInvoker implements ActionInvoker {

    private static final Logger logger = LoggerFactory.getLogger("org.mojavemvc");

    private final HttpServletRequest request;
    private final HttpServletResponse response;
    private final ControllerDatabase controllerDb;
    private final Injector injector;
    private final String controller;
    private final String action;
    private final Map<String, Object> parameterMap;

    public HttpActionInvoker(HttpServletRequest request, HttpServletResponse response, ControllerDatabase controllerDb,
            RoutedRequest routed, Injector injector) {

        this.request = request;
        this.response = response;
        this.controllerDb = controllerDb;
        this.injector = injector;

        String cntrl = routed.getController();
        controller = (cntrl == null || cntrl.trim().length() == 0) ? "" : cntrl;

        String actn = routed.getAction();
        action = (actn == null || actn.trim().length() == 0) ? "" : actn;
       
        this.parameterMap = routed.getParameterMap();
    }

    public View invokeAction(Object actionController, ActionSignature actionSignature) throws Exception {

        Class<?> actionControllerClass = actionController.getClass();
        logInitMessage(actionSignature, actionControllerClass);
        return invokeActionMethod(actionController, actionSignature, actionControllerClass);
    }

    private void logInitMessage(ActionSignature actionSignature, Class<?> actionControllerClass) {

        String message = "";
        if (actionSignature != null) {
            message = "invoking action " + actionSignature.methodName();
        } else {
            message = "invoking default action";
        }
        message += " for " + actionControllerClass.getName();
        logger.debug(message);
    }

    private View invokeActionMethod(Object actionController, ActionSignature actionSignature,
            Class<?> actionControllerClass) throws Exception {

        View view = null;

        Object[] args = actionSignature.getArgs(parameterMap, request.getInputStream());
        Annotation[] actionAnnotations = actionSignature.getAnnotations();

        List<Object> classInterceptors = createInterceptors(controllerDb.getInterceptorsFor(actionControllerClass));

        List<Object> methodInterceptors = createInterceptorsForAction(actionSignature, actionControllerClass);

        for (Object interceptor : classInterceptors) {

            view = invokeBeforeActionIfRequired(interceptor, actionAnnotations,
                    controllerDb.getBeforeActionMethodForInterceptor(interceptor.getClass()), args);
            if (view != null) {
                return view;
            }
        }

        for (Object interceptor : methodInterceptors) {

            view = invokeBeforeActionIfRequired(interceptor, actionAnnotations,
                    controllerDb.getBeforeActionMethodForInterceptor(interceptor.getClass()), args);
            if (view != null) {
                return view;
            }
        }

        view = invokeBeforeActionIfRequired(actionController, actionAnnotations,
                controllerDb.getBeforeActionMethodFor(actionControllerClass), args);

        if (view != null) {
            return view;
        }

        FastClass actionFastClass = controllerDb.getFastClass(actionControllerClass);
        Object entity = actionFastClass.invoke(actionSignature.fastIndex(), actionController, args);
        View marshalledEntity = actionSignature.marshall(entity);
        view = marshalledEntity;
        logger.debug("invoked " + actionSignature.methodName() + " for " + actionControllerClass.getName());

        View afterActionView = invokeAfterActionIfRequired(actionController, actionAnnotations,
                controllerDb.getAfterActionMethodFor(actionControllerClass),
                args, entity, marshalledEntity);

        if (afterActionView != null) {
            view = afterActionView;
        }

        for (Object interceptor : methodInterceptors) {

            View interceptorView = invokeAfterActionIfRequired(interceptor, actionAnnotations,
                    controllerDb.getAfterActionMethodForInterceptor(interceptor.getClass()),
                    args, entity, marshalledEntity);
            if (interceptorView != null) {
                view = interceptorView;
                break;
            }
        }

        for (Object interceptor : classInterceptors) {

            View interceptorView = invokeAfterActionIfRequired(interceptor, actionAnnotations,
                    controllerDb.getAfterActionMethodForInterceptor(interceptor.getClass()),
                    args, entity, marshalledEntity);
            if (interceptorView != null) {
                view = interceptorView;
                break;
            }
        }

        return view;
    }

    private List<Object> createInterceptorsForAction(ActionSignature actionSignature,
            Class<?> actionControllerClass) throws Exception {

        List<Class<?>> interceptorClasses = null;
        interceptorClasses = actionSignature.getInterceptorClasses(controllerDb, actionControllerClass, action);
        return createInterceptors(interceptorClasses);
    }

    private List<Object> createInterceptors(List<Class<?>> interceptorClasses) throws Exception {

        List<Object> interceptors = new ArrayList<Object>();
        if (interceptorClasses != null) {
            for (Class<?> interceptorClass : interceptorClasses) {

                /* use the Guice Injector */
                Object interceptor = injector.getInstance(interceptorClass);
                interceptors.add(interceptor);
            }
        }
        return interceptors;
    }

    private View invokeBeforeActionIfRequired(Object instance, Annotation[] actionAnnotations,
            ActionSignature interceptorMethod, Object[] actionArgs)
            throws Exception {

        return invokeBeforeOrAfterActionIfRequired(instance, actionAnnotations,
                interceptorMethod, actionArgs, null, null, "before");
    }

    private View invokeAfterActionIfRequired(Object instance, Annotation[] actionAnnotations,
            ActionSignature interceptorMethod, Object[] actionArgs, Object entity, View marshalledEntity)
            throws Exception {

        return invokeBeforeOrAfterActionIfRequired(instance, actionAnnotations,
                interceptorMethod, actionArgs, entity, marshalledEntity, "after");
    }

    private View invokeBeforeOrAfterActionIfRequired(Object instance, Annotation[] actionAnnotations,
            ActionSignature interceptorMethod, Object[] actionArgs, Object entity, View marshalledEntity,
            String which) throws Exception {

        View view = null;

        if (interceptorMethod != null) {
            /*
             * we've already validated that there are no method parameters when
             * creating the controller database
             */

            FastClass actionFastClass = controllerDb.getFastClass(instance.getClass());
            Object returnObj = actionFastClass.invoke(interceptorMethod.fastIndex(), instance,
                    getBeforeOrAfterActionArgs(interceptorMethod.parameterTypes(), actionArgs,
                            actionAnnotations, entity, marshalledEntity));

            if (returnObj != null && returnObj instanceof View) {
                view = (View) returnObj;
            }
            logger.debug("invoked " + which + " action for " + instance.getClass().getName());

            /*
             * if there is a before or after action method, it is possible that
             * another view may have been dispatched to from that method;
             * therefore if the response has been committed, we should return an
             * empty view NOTE: this will not work if the servlet container does
             * not set the response to being committed after the dispatch
             */
            if (response.isCommitted())
                return new EmptyView();
        }

        return view;
    }

    private Object[] getBeforeOrAfterActionArgs(Class<?>[] paramterTypes, Object[] actionArgs,
            Annotation[] actionAnnotations, Object entity, View marshalledEntity) {

        Object[] args = new Object[] {};

        if (paramterTypes != null && paramterTypes.length == 1 && paramterTypes[0].equals(RequestContext.class)) {

            args = new Object[1];
            args[0] = new RequestContext(request, response, actionArgs,
                    action, controller, actionAnnotations, entity, marshalledEntity);
        }

        return args;
    }
}
TOP

Related Classes of org.mojavemvc.core.HttpActionInvoker

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.