com.bstek.dorado.view.resolver.VelocityInterceptorDirective.java Source code

Java tutorial

Introduction

Here is the source code for com.bstek.dorado.view.resolver.VelocityInterceptorDirective.java

Source

/*
 * This file is part of Dorado 7.x (http://dorado7.bsdn.org).
 * 
 * Copyright (c) 2002-2012 BSTEK Corp. All rights reserved.
 * 
 * This file is dual-licensed under the AGPLv3 (http://www.gnu.org/licenses/agpl-3.0.html) 
 * and BSDN commercial (http://www.bsdn.org/licenses) licenses.
 * 
 * If you are unsure which license is appropriate for your use, please contact the sales department
 * at http://www.bstek.com/contact.
 */

package com.bstek.dorado.view.resolver;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.context.Context;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.parser.node.Node;

import com.bstek.dorado.core.bean.BeanFactoryUtils;
import com.bstek.dorado.data.method.MethodAutoMatchingUtils;
import com.bstek.dorado.view.View;
import com.bstek.dorado.view.ViewElement;

/**
 * @author Benny Bao (mailto:benny.bao@bstek.com)
 * @since 2011-1-24
 */
public class VelocityInterceptorDirective extends AbstractDirective {
    @Override
    public String getName() {
        return "interceptor";
    }

    @Override
    public int getType() {
        return LINE;
    }

    @Override
    public boolean render(InternalContextAdapter contextAdapter, Writer writer, Node node)
            throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
        try {
            intercept(contextAdapter, writer, node);
        } catch (Exception e) {
            processException(contextAdapter, writer, e);
        }
        return true;
    }

    @SuppressWarnings("rawtypes")
    protected void intercept(InternalContextAdapter contextAdapter, Writer writer, Node node) throws Exception {
        int paramNum = node.jjtGetNumChildren();
        if (paramNum == 0) {
            throw new IllegalArgumentException("No interceptor name defined in #interceptor.");
        }
        String interceptorName = (String) node.jjtGetChild(0).value(contextAdapter);
        if (StringUtils.isEmpty(interceptorName)) {
            throw new IllegalArgumentException("The interceptor name defined in #interceptor can not be empty.");
        }
        if (interceptorName.indexOf('#') <= 0) {
            throw new IllegalArgumentException("Invalid interceptor name [" + interceptorName + "].");
        }
        String beanName = StringUtils.substringBefore(interceptorName, "#");
        String methodName = StringUtils.substringAfter(interceptorName, "#");
        if (StringUtils.isEmpty(methodName)) {
            throw new IllegalArgumentException("Invalid interceptor name [" + interceptorName + "].");
        }

        if (paramNum > 2) {
            throw new IllegalArgumentException("Too more arguments defined in #interceptor.");
        }

        Map parameterMap = null;
        if (paramNum == 2) {
            parameterMap = (Map) node.jjtGetChild(1).value(contextAdapter);
        }

        Object bean = BeanFactoryUtils.getBean(beanName);
        Method[] methods = MethodAutoMatchingUtils.getMethodsByName(bean.getClass(), methodName);
        if (methods.length == 0) {
            throw new IllegalArgumentException("No method found for [" + interceptorName + "].");
        } else if (methods.length > 1) {
            throw new IllegalArgumentException("More than one method found for [" + interceptorName + "].");
        }
        Method method = methods[0];
        View view = (View) contextAdapter.get("view");

        Class<?>[] parameterTypes = method.getParameterTypes();
        String[] parameterNames = MethodAutoMatchingUtils.getParameterNames(method);
        Object[] parameters = new Object[parameterTypes.length];
        int i = 0;
        for (Class<?> parameterType : parameterTypes) {
            if (Writer.class.isAssignableFrom(parameterType)) {
                /* Writer */
                parameters[i] = writer;
            } else if (Context.class.isAssignableFrom(parameterType)) {
                /* Velocity Context */
                parameters[i] = contextAdapter;
            } else if (ViewElement.class.isAssignableFrom(parameterType)) {
                /* Component or View */
                String parameterName = parameterNames[i];
                if ("view".equals(parameterName)) {
                    parameters[i] = view;
                } else {
                    parameters[i] = view.getViewElement(parameterName);
                }
            } else if (parameterMap != null) {
                /* from ParameterMap */
                String parameterName = parameterNames[i];
                parameters[i] = parameterMap.get(parameterName);
            }
            i++;
        }

        method.invoke(bean, parameters);
    }
}