View Javadoc
1   /*******************************************************************************
2    * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian
3    * Thomschke.
4    * 
5    * All Rights Reserved. This program and the accompanying materials
6    * are made available under the terms of the Eclipse Public License v1.0
7    * which accompanies this distribution, and is available at
8    * http://www.eclipse.org/legal/epl-v10.html
9    * 
10   * Contributors:
11   *     Sebastian Thomschke - initial implementation.
12   *******************************************************************************/
13  package net.sf.oval.guard;
14  
15  import java.lang.reflect.AccessibleObject;
16  import java.lang.reflect.Constructor;
17  import java.lang.reflect.Field;
18  import java.lang.reflect.Method;
19  import java.util.WeakHashMap;
20  
21  import net.sf.oval.exception.ReflectionException;
22  import net.sf.oval.internal.util.ReflectionUtils;
23  
24  import org.aspectj.lang.JoinPoint;
25  import org.aspectj.lang.reflect.ConstructorSignature;
26  import org.aspectj.lang.reflect.MethodSignature;
27  
28  /**
29   * This class determines the names of constructor and method parameters based on the static 
30   * JoinPoint fields added to the classes by the AspectJ compiler.
31   *  
32   * @author Sebastian Thomschke
33   */
34  public class ParameterNameResolverAspectJImpl implements ParameterNameResolver
35  {
36  	private final WeakHashMap<AccessibleObject, String[]> parameterNamesCache = new WeakHashMap<AccessibleObject, String[]>();
37  
38  	private void determineParamterNames(final Class< ? > clazz) throws IllegalArgumentException, IllegalAccessException
39  	{
40  		assert clazz != null;
41  
42  		for (final Field field : clazz.getDeclaredFields())
43  		{
44  			// search for static fields of type JoinPoint.StaticPart
45  			if (ReflectionUtils.isStatic(field) && field.getType() == JoinPoint.StaticPart.class)
46  			{
47  				// access the StaticPart object
48  				field.setAccessible(true);
49  				final JoinPoint.StaticPart staticPart = (JoinPoint.StaticPart) field.get(null);
50  				if (staticPart == null)
51  				{
52  					break;
53  				}
54  
55  				if (staticPart.getSignature() instanceof ConstructorSignature)
56  				{
57  					final ConstructorSignature sig = (ConstructorSignature) staticPart.getSignature();
58  					final String[] parameterNames = sig.getParameterNames();
59  
60  					final Constructor< ? > constr = sig.getConstructor();
61  
62  					if (parameterNames.length > 0)
63  					{
64  						parameterNamesCache.put(constr, parameterNames);
65  					}
66  				}
67  				else if (staticPart.getSignature() instanceof MethodSignature)
68  				{
69  					final MethodSignature sig = (MethodSignature) staticPart.getSignature();
70  					final String[] parameterNames = sig.getParameterNames();
71  
72  					final Method method = sig.getMethod();
73  
74  					if (parameterNames.length > 0)
75  					{
76  						parameterNamesCache.put(method, parameterNames);
77  					}
78  				}
79  			}
80  		}
81  	}
82  
83  	/**
84  	 * {@inheritDoc}
85  	 */
86  	public String[] getParameterNames(final Constructor< ? > constructor) throws ReflectionException
87  	{
88  		/*
89  		 * intentionally the following code is not synchronized
90  		 */
91  		String[] parameterNames = parameterNamesCache.get(constructor);
92  		if (parameterNames == null)
93  		{
94  			try
95  			{
96  				determineParamterNames(constructor.getDeclaringClass());
97  				parameterNames = parameterNamesCache.get(constructor);
98  			}
99  			catch (final IllegalArgumentException e)
100 			{
101 				throw new ReflectionException("Cannot detemine parameter names for constructor " + constructor, e);
102 			}
103 			catch (final IllegalAccessException e)
104 			{
105 				throw new ReflectionException("Cannot detemine parameter names for constructor " + constructor, e);
106 			}
107 		}
108 
109 		if (parameterNames == null)
110 		{
111 			final int parameterCount = constructor.getParameterTypes().length;
112 			parameterNames = new String[parameterCount];
113 			for (int i = 0; i < parameterCount; i++)
114 			{
115 				parameterNames[i] = "parameter" + i;
116 			}
117 			parameterNamesCache.put(constructor, parameterNames);
118 		}
119 		return parameterNames;
120 	}
121 
122 	/**
123 	 * {@inheritDoc}
124 	 */
125 	public String[] getParameterNames(final Method method) throws ReflectionException
126 	{
127 		/*
128 		 * intentionally the following code is not synchronized
129 		 */
130 		String[] parameterNames = parameterNamesCache.get(method);
131 		if (parameterNames == null)
132 		{
133 			try
134 			{
135 				determineParamterNames(method.getDeclaringClass());
136 				parameterNames = parameterNamesCache.get(method);
137 			}
138 			catch (final IllegalArgumentException e)
139 			{
140 				throw new ReflectionException("Cannot detemine parameter names for method " + method, e);
141 			}
142 			catch (final IllegalAccessException e)
143 			{
144 				throw new ReflectionException("Cannot detemine parameter names for method " + method, e);
145 			}
146 		}
147 
148 		if (parameterNames == null)
149 		{
150 			final int parameterCount = method.getParameterTypes().length;
151 			parameterNames = new String[parameterCount];
152 			for (int i = 0; i < parameterCount; i++)
153 			{
154 				parameterNames[i] = "parameter" + i;
155 			}
156 			parameterNamesCache.put(method, parameterNames);
157 		}
158 		return parameterNames;
159 	}
160 }