Java tutorial
/* * 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; } }