View Javadoc

1   package org.seasar.cubby.aop;
2   
3   import java.io.Serializable;
4   import java.lang.reflect.Method;
5   import java.util.HashSet;
6   import java.util.Set;
7   import java.util.regex.Pattern;
8   
9   import org.seasar.cubby.util.CubbyUtils;
10  import org.seasar.framework.aop.Pointcut;
11  import org.seasar.framework.exception.EmptyRuntimeException;
12  
13  /**
14   * アクションメソッドに適用される {@link Pointcut}。
15   * 
16   * @author baba
17   */
18  public class ActionMethodPointcutImpl implements Pointcut, Serializable {
19  
20  	private static final long serialVersionUID = -5701826062675617117L;
21  
22  	private String[] methodNames;
23  
24  	private Pattern[] patterns;
25  
26  	private Method method;
27  
28  	/**
29  	 * {@link ActionMethodPointcutImpl}を作成します。
30  	 * 
31  	 * @param targetClass
32  	 * @throws EmptyRuntimeException
33  	 */
34  	public ActionMethodPointcutImpl(final Class<?> targetClass)
35  			throws EmptyRuntimeException {
36  
37  		if (targetClass == null) {
38  			throw new EmptyRuntimeException("targetClass");
39  		}
40  		setMethodNames(getMethodNames(targetClass));
41  	}
42  
43  	/**
44  	 * {@link ActionMethodPointcutImpl}を作成します。
45  	 * 
46  	 * @param methodNames
47  	 * @throws EmptyRuntimeException
48  	 */
49  	public ActionMethodPointcutImpl(final String[] methodNames)
50  			throws EmptyRuntimeException {
51  
52  		if (methodNames == null || methodNames.length == 0) {
53  			throw new EmptyRuntimeException("methodNames");
54  		}
55  		setMethodNames(methodNames);
56  	}
57  
58  	/**
59  	 * {@link ActionMethodPointcutImpl}を作成します。
60  	 * 
61  	 * @param method
62  	 *            メソッド
63  	 */
64  	public ActionMethodPointcutImpl(final Method method) {
65  		this.method = method;
66  	}
67  
68  	public boolean isApplied(final Method targetMethod) {
69  		if (method != null) {
70  			return method.equals(targetMethod);
71  		}
72  
73  		if (!CubbyUtils.isActionMethod(targetMethod)) {
74  			return false;
75  		}
76  
77  		final String methodName = targetMethod.getName();
78  		for (int i = 0; i < patterns.length; ++i) {
79  			if (patterns[i].matcher(methodName).matches()) {
80  				return true;
81  			}
82  		}
83  		return false;
84  	}
85  
86  	/**
87  	 * 対象になったメソッド名の配列を返します。
88  	 * 
89  	 * @return 対象になったメソッド名の配列
90  	 */
91  	public String[] getMethodNames() {
92  		return methodNames;
93  	}
94  
95  	private void setMethodNames(final String[] methodNames) {
96  		this.methodNames = methodNames;
97  		patterns = new Pattern[methodNames.length];
98  		for (int i = 0; i < patterns.length; ++i) {
99  			patterns[i] = Pattern.compile(methodNames[i]);
100 		}
101 	}
102 
103 	private static String[] getMethodNames(final Class<?> targetClass) {
104 		final Set<String> methodNameSet = new HashSet<String>();
105 		if (targetClass.isInterface()) {
106 			addInterfaceMethodNames(methodNameSet, targetClass);
107 		}
108 		for (Class<?> clazz = targetClass; clazz != Object.class
109 				&& clazz != null; clazz = clazz.getSuperclass()) {
110 			final Class<?>[] interfaces = clazz.getInterfaces();
111 			for (int i = 0; i < interfaces.length; ++i) {
112 				addInterfaceMethodNames(methodNameSet, interfaces[i]);
113 			}
114 		}
115 		return methodNameSet.toArray(new String[methodNameSet.size()]);
116 
117 	}
118 
119 	private static void addInterfaceMethodNames(
120 			final Set<String> methodNameSet, final Class<?> interfaceClass) {
121 		final Method[] methods = interfaceClass.getDeclaredMethods();
122 		for (int j = 0; j < methods.length; j++) {
123 			methodNameSet.add(methods[j].getName());
124 		}
125 		final Class<?>[] interfaces = interfaceClass.getInterfaces();
126 		for (int i = 0; i < interfaces.length; ++i) {
127 			addInterfaceMethodNames(methodNameSet, interfaces[i]);
128 		}
129 	}
130 
131 }