001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.web.handler; 017 018import com.jfinal.aop.Interceptor; 019import com.jfinal.aop.Invocation; 020import com.jfinal.core.Action; 021import com.jfinal.core.Controller; 022import io.jboot.aop.InterceptorBuilderManager; 023import io.jboot.aop.InterceptorCache; 024 025import java.lang.reflect.InvocationTargetException; 026import java.lang.reflect.Method; 027 028/** 029 * @author michael yang (fuhai999@gmail.com) 030 */ 031public class JbootActionInvocation extends Invocation { 032 033 protected Action action; 034 protected Object target; 035 protected Object[] args; 036 037 protected Interceptor[] inters; 038 protected int index = 0; 039 040 protected Object returnValue; 041 042 043 protected static InterceptorBuilderManager builderManager = InterceptorBuilderManager.me(); 044 045 public JbootActionInvocation(Action action, Controller controller) { 046 047 this.action = action; 048 this.inters = buildInterceptors(action); 049 this.target = controller; 050 051 this.args = action.getParameterGetter().get(action, controller); 052 } 053 054 055 protected Interceptor[] buildInterceptors(Action action) { 056 057 InterceptorCache.MethodKey key = InterceptorCache.getMethodKey(action.getControllerClass(), action.getMethod()); 058 Interceptor[] inters = InterceptorCache.get(key); 059 if (inters == null) { 060 inters = action.getInterceptors(); 061 inters = builderManager.build(action.getControllerClass(), action.getMethod(), inters); 062 InterceptorCache.put(key, inters); 063 } 064 065 return inters; 066 } 067 068 069 @Override 070 public void invoke() { 071 if (index < inters.length) { 072 inters[index++].intercept(this); 073 } else if (index++ == inters.length) { // index++ ensure invoke action only one time 074 try { 075 // Invoke the action 076 returnValue = action.getMethod().invoke(target, args); 077 } catch (InvocationTargetException e) { 078 Throwable t = e.getTargetException(); 079 if (t == null) { 080 t = e; 081 } 082 throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); 083 } catch (RuntimeException e) { 084 throw e; 085 } catch (Throwable t) { 086 throw new RuntimeException(t); 087 } 088 } 089 } 090 091 092 @Override 093 public Object getArg(int index) { 094 if (index >= args.length) { 095 throw new ArrayIndexOutOfBoundsException(); 096 } 097 return args[index]; 098 } 099 100 101 @Override 102 public void setArg(int index, Object value) { 103 if (index >= args.length) { 104 throw new ArrayIndexOutOfBoundsException(); 105 } 106 args[index] = value; 107 } 108 109 110 @Override 111 public Object[] getArgs() { 112 return args; 113 } 114 115 116 @Override 117 public <T> T getTarget() { 118 return (T) target; 119 } 120 121 /** 122 * Return the method of this action. 123 * <p> 124 * You can getMethod.getAnnotations() to get annotation on action method to do more things 125 */ 126 @Override 127 public Method getMethod() { 128 return action.getMethod(); 129 } 130 131 /** 132 * Return the method name of this action's method. 133 */ 134 @Override 135 public String getMethodName() { 136 return action.getMethodName(); 137 } 138 139 /** 140 * Get the return value of the target method 141 */ 142 @Override 143 public <T> T getReturnValue() { 144 return (T) returnValue; 145 } 146 147 148 @Override 149 public void setReturnValue(Object returnValue) { 150 this.returnValue = returnValue; 151 } 152 // --------- 153 154 /** 155 * Return the controller of this action. 156 */ 157 @Override 158 public Controller getController() { 159 return (Controller) target; 160 } 161 162 /** 163 * Return the action key. 164 * actionKey = controllerPath + methodName 165 */ 166 @Override 167 public String getActionKey() { 168 return action.getActionKey(); 169 } 170 171 /** 172 * Return the controller path. 173 */ 174 @Override 175 public String getControllerPath() { 176 return action.getControllerPath(); 177 } 178 179 /** 180 * 该方法已改名为 getControllerPath() 181 */ 182 @Override 183 @Deprecated 184 public String getControllerKey() { 185 return getControllerPath(); 186 } 187 188 /** 189 * Return view path of this controller. 190 */ 191 @Override 192 public String getViewPath() { 193 return action.getViewPath(); 194 } 195 196 /** 197 * return true if it is action invocation. 198 */ 199 @Override 200 public boolean isActionInvocation() { 201 return action != null; 202 } 203}