com.laxser.blitz.web.ControllerInterceptorAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.laxser.blitz.web.ControllerInterceptorAdapter.java

Source

/*
 * Copyright 2007-2009 the original author or authors.
 *
 * 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 com.laxser.blitz.web;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.laxser.blitz.advancedinterceptor.ActionSelector;
import com.laxser.blitz.advancedinterceptor.DispatcherSelector;
import com.laxser.blitz.advancedinterceptor.Named;
import com.laxser.blitz.advancedinterceptor.Ordered;
import com.laxser.blitz.web.impl.thread.AfterCompletion;
import com.laxser.blitz.web.instruction.Instruction;

/**
 * @author laxser Date 2012-3-30 ?11:20:44
 * @contact [duqifan@gmail.com]
 * @ControllerInterceptorAdapter.java
 */
public class ControllerInterceptorAdapter
        implements Named, Ordered, ControllerInterceptor, AfterCompletion, ActionSelector, DispatcherSelector {

    protected Log logger = LogFactory.getLog(getClass());

    protected String name;

    protected int priority;

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getPriority() {
        return priority;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

    @Override
    public final boolean isForAction(Class<?> controllerClazz, Method actionMethod) {
        // false?
        if (!checkRequiredAnnotations(controllerClazz, actionMethod)) {
            return false;
        }
        // true??
        if (checkDenyAnnotations(controllerClazz, actionMethod)) {
            return false;
        }
        return isForAction(actionMethod, controllerClazz);
    }

    protected boolean isForAction(Method actionMethod, Class<?> controllerClazz) {
        return true;
    }

    @Override
    public boolean isForDispatcher(Dispatcher dispatcher) {
        return true;
    }

    @Override
    public final Object roundInvocation(Invocation inv, InvocationChain chain) throws Exception {
        // before
        Object instruction = this.before(inv);

        // break the invocation?
        if (instruction != null && !Boolean.TRUE.equals(instruction)) {

            // if false, don't render anything
            if (Boolean.FALSE.equals(instruction)) {
                instruction = null;
            }
            return instruction; // break and return
        }

        // next
        instruction = round(inv, chain);

        // after
        return after(inv, instruction);
    }

    /**
     * ?true(null)<br>
     * ???action(? ) {@link Instruction}
     * ????(?)
     * <p>
     * ???????? 
     * {@link #after(Invocation, Object)}
     * {@link #afterCompletion(Invocation, Throwable)}
     * <p>
     * 
     * @param inv
     * @return
     * @throws Exception
     */
    protected Object before(Invocation inv) throws Exception {
        return Boolean.TRUE;
    }

    /**
     * 
     * @param inv
     * @param chain
     * @return
     * @throws Exception
     */
    protected Object round(Invocation inv, InvocationChain chain) throws Exception {
        return chain.doNext();
    }

    /**
     * ???????
     * <p>
     * null?instruction??<br>
     * ?????
     * 
     * @param inv
     * @param instruction
     * @return
     * @throws Exception
     */
    protected Object after(Invocation inv, Object instruction) throws Exception {
        return instruction;
    }

    @Override
    public void afterCompletion(Invocation inv, Throwable ex) throws Exception {
    }

    @Override
    public String toString() {
        return getName();
    }

    protected static ListBuilder createList(int size) {
        return new ListBuilder(size);
    }

    public static class ListBuilder {

        List<Class<? extends Annotation>> list;

        ListBuilder(int size) {
            list = new ArrayList<Class<? extends Annotation>>(size);
        }

        public ListBuilder add(Class<? extends Annotation> a) {
            list.add(a);
            return this;
        }

        public List<Class<? extends Annotation>> getList() {
            return list;
        }
    }

    /**
     * false?
     * 
     * @param controllerClazz
     *            
     * @param actionMethod
     *            ?
     * @return
     */
    protected final boolean checkRequiredAnnotations(Class<?> controllerClazz, Method actionMethod) {
        List<Class<? extends Annotation>> requiredAnnotations = getRequiredAnnotationClasses();
        if (requiredAnnotations == null || requiredAnnotations.size() == 0) {
            return true;
        }
        for (Class<? extends Annotation> requiredAnnotation : requiredAnnotations) {
            if (requiredAnnotation == null) {
                continue;
            }
            BitSet scopeSet = getAnnotationScope(requiredAnnotation);
            if (scopeSet.get(AnnotationScope.METHOD.ordinal())) {
                if (actionMethod.isAnnotationPresent(requiredAnnotation)) {
                    return checkAnnotation(actionMethod.getAnnotation(requiredAnnotation));
                }
            }
            if (scopeSet.get(AnnotationScope.CLASS.ordinal())) {
                if (controllerClazz.isAnnotationPresent(requiredAnnotation)) {
                    return checkAnnotation(actionMethod.getAnnotation(requiredAnnotation));
                }
            }
            if (scopeSet.get(AnnotationScope.ANNOTATION.ordinal())) {
                for (Annotation annotation : actionMethod.getAnnotations()) {
                    if (annotation.annotationType().isAnnotationPresent(requiredAnnotation)) {
                        return checkAnnotation(actionMethod.getAnnotation(requiredAnnotation));
                    }
                }
                for (Annotation annotation : controllerClazz.getAnnotations()) {
                    if (annotation.annotationType().isAnnotationPresent(requiredAnnotation)) {
                        return checkAnnotation(actionMethod.getAnnotation(requiredAnnotation));
                    }
                }
            }
        }
        return false;
    }

    /**
     * : METHOD(), CLASS(), ANNOTATION()
     */
    public static enum AnnotationScope {
        METHOD, CLASS, ANNOTATION;

        public static BitSet getMethodAndClassScope() {
            BitSet bitSet = new BitSet();
            bitSet.set(METHOD.ordinal());
            bitSet.set(CLASS.ordinal());
            return bitSet;
        }

        public static BitSet getMethodAndClassAndAnnotationScope() {
            BitSet bitSet = new BitSet();
            bitSet.set(METHOD.ordinal());
            bitSet.set(CLASS.ordinal());
            bitSet.set(ANNOTATION.ordinal());
            return bitSet;
        }
    }

    /**
     *  BitSet ?
     * 
     * @param annotationType
     * @return
     */
    protected BitSet getAnnotationScope(Class<? extends Annotation> annotationType) {
        return AnnotationScope.getMethodAndClassScope();
    }

    /**
     * true??
     * 
     * @param controllerClazz
     * @param actionMethod
     * @return
     */
    protected final boolean checkDenyAnnotations(Class<?> controllerClazz, Method actionMethod) {
        List<Class<? extends Annotation>> denyAnnotations = getDenyAnnotationClasses();
        if (denyAnnotations == null || denyAnnotations.size() == 0) {
            return false;
        }
        for (Class<? extends Annotation> denyAnnotation : denyAnnotations) {
            if (denyAnnotation == null) {
                continue;
            }
            BitSet scopeSet = getAnnotationScope(denyAnnotation);
            if (scopeSet.get(AnnotationScope.METHOD.ordinal())) {
                if (actionMethod.isAnnotationPresent(denyAnnotation)) {
                    return checkAnnotation(actionMethod.getAnnotation(denyAnnotation));
                }
            }
            if (scopeSet.get(AnnotationScope.CLASS.ordinal())) {
                if (controllerClazz.isAnnotationPresent(denyAnnotation)) {
                    return checkAnnotation(actionMethod.getAnnotation(denyAnnotation));
                }
            }
            if (scopeSet.get(AnnotationScope.ANNOTATION.ordinal())) {
                for (Annotation annotation : actionMethod.getAnnotations()) {
                    if (annotation.annotationType().isAnnotationPresent(denyAnnotation)) {
                        return checkAnnotation(actionMethod.getAnnotation(denyAnnotation));
                    }
                }
                for (Annotation annotation : controllerClazz.getAnnotations()) {
                    if (annotation.annotationType().isAnnotationPresent(denyAnnotation)) {
                        return checkAnnotation(actionMethod.getAnnotation(denyAnnotation));
                    }
                }
            }
        }
        return false;
    }

    /**
     * ?{@link #checkRequiredAnnotations(Class, Method)}/
     * {@link #checkDenyAnnotations(Class, Method)}
     * annotationtrue/false<br>
     * 
     * 
     * 
     * 
     * @param annotation
     * @return
     */
    protected boolean checkAnnotation(Annotation annotation) {
        return true;
    }

    protected List<Class<? extends Annotation>> getRequiredAnnotationClasses() {
        Class<? extends Annotation> clazz = getRequiredAnnotationClass();
        if (clazz != null) {
            List<Class<? extends Annotation>> list = new ArrayList<Class<? extends Annotation>>(2);
            list.add(clazz);
            return list;
        }
        return Collections.emptyList();
    }

    protected Class<? extends Annotation> getRequiredAnnotationClass() {
        return null;
    }

    protected List<Class<? extends Annotation>> getDenyAnnotationClasses() {
        Class<? extends Annotation> clazz = getDenyAnnotationClass();
        if (clazz != null) {
            List<Class<? extends Annotation>> list = new ArrayList<Class<? extends Annotation>>();
            list.add(clazz);
            return list;
        }
        return Collections.emptyList();
    }

    protected Class<? extends Annotation> getDenyAnnotationClass() {
        return null;
    }

}