• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.introspect;
2 
3 import java.lang.reflect.*;
4 
5 import com.fasterxml.jackson.databind.JavaType;
6 import com.fasterxml.jackson.databind.util.ClassUtil;
7 
8 public final class AnnotatedMethod
9     extends AnnotatedWithParams
10     implements java.io.Serializable
11 {
12     private static final long serialVersionUID = 1L;
13 
14     final protected transient Method _method;
15 
16     // // Simple lazy-caching:
17 
18     protected Class<?>[] _paramClasses;
19 
20     /**
21      * Field that is used to make JDK serialization work with this
22      * object.
23      *
24      * @since 2.1
25      */
26     protected Serialization _serialization;
27 
28     /*
29     /*****************************************************
30     /* Life-cycle
31     /*****************************************************
32      */
33 
AnnotatedMethod(TypeResolutionContext ctxt, Method method, AnnotationMap classAnn, AnnotationMap[] paramAnnotations)34     public AnnotatedMethod(TypeResolutionContext ctxt, Method method,
35             AnnotationMap classAnn, AnnotationMap[] paramAnnotations)
36     {
37         super(ctxt, classAnn, paramAnnotations);
38         if (method == null) {
39             throw new IllegalArgumentException("Cannot construct AnnotatedMethod with null Method");
40         }
41         _method = method;
42     }
43 
44     /**
45      * Method used for JDK serialization support
46      * @since 2.1
47      */
AnnotatedMethod(Serialization ser)48     protected AnnotatedMethod(Serialization ser)
49     {
50         super(null, null, null);
51         _method = null;
52         _serialization = ser;
53     }
54 
55     @Override
withAnnotations(AnnotationMap ann)56     public AnnotatedMethod withAnnotations(AnnotationMap ann) {
57         return new AnnotatedMethod(_typeContext, _method, ann, _paramAnnotations);
58     }
59 
60 
61     @Override
getAnnotated()62     public Method getAnnotated() { return _method; }
63 
64     @Override
getModifiers()65     public int getModifiers() { return _method.getModifiers(); }
66 
67     @Override
getName()68     public String getName() { return _method.getName(); }
69 
70     /**
71      * For methods, this returns declared return type, which is only
72      * useful with getters (setters do not return anything; hence `Void`
73      * would be returned here)
74      */
75     @Override
getType()76     public JavaType getType() {
77         return _typeContext.resolveType(_method.getGenericReturnType());
78     }
79 
80     /**
81      * For methods, this returns declared return type, which is only
82      * useful with getters (setters do not usually return anything;
83      * hence "void" type is returned here)
84      */
85     @Override
getRawType()86     public Class<?> getRawType() {
87         return _method.getReturnType();
88     }
89 
90     /*
91     /*****************************************************
92     /* AnnotatedWithParams
93     /*****************************************************
94      */
95 
96     @Override
call()97     public final Object call() throws Exception {
98         return _method.invoke(null);
99     }
100 
101     @Override
call(Object[] args)102     public final Object call(Object[] args) throws Exception {
103         return _method.invoke(null, args);
104     }
105 
106     @Override
call1(Object arg)107     public final Object call1(Object arg) throws Exception {
108         return _method.invoke(null, arg);
109     }
110 
callOn(Object pojo)111     public final Object callOn(Object pojo) throws Exception {
112         return _method.invoke(pojo, (Object[]) null);
113     }
114 
callOnWith(Object pojo, Object... args)115     public final Object callOnWith(Object pojo, Object... args) throws Exception {
116         return _method.invoke(pojo, args);
117     }
118 
119     /*
120     /********************************************************
121     /* AnnotatedMember impl
122     /********************************************************
123      */
124 
125     @Override
getParameterCount()126     public int getParameterCount() {
127         return getRawParameterTypes().length;
128     }
129 
130     @Override
getRawParameterType(int index)131     public Class<?> getRawParameterType(int index)
132     {
133         Class<?>[] types = getRawParameterTypes();
134         return (index >= types.length) ? null : types[index];
135     }
136 
137     @Override
getParameterType(int index)138     public JavaType getParameterType(int index) {
139         Type[] types = _method.getGenericParameterTypes();
140         if (index >= types.length) {
141             return null;
142         }
143         return _typeContext.resolveType(types[index]);
144     }
145 
146     @Override
147     @Deprecated // since 2.7
getGenericParameterType(int index)148     public Type getGenericParameterType(int index) {
149         Type[] types = getGenericParameterTypes();
150         if (index >= types.length) {
151             return null;
152         }
153         return types[index];
154     }
155 
156     @Override
getDeclaringClass()157     public Class<?> getDeclaringClass() { return _method.getDeclaringClass(); }
158 
159     @Override
getMember()160     public Method getMember() { return _method; }
161 
162     @Override
setValue(Object pojo, Object value)163     public void setValue(Object pojo, Object value) throws IllegalArgumentException
164     {
165         try {
166             _method.invoke(pojo, value);
167         } catch (IllegalAccessException | InvocationTargetException e) {
168             throw new IllegalArgumentException("Failed to setValue() with method "
169                     +getFullName()+": "+e.getMessage(), e);
170         }
171     }
172 
173     @Override
getValue(Object pojo)174     public Object getValue(Object pojo) throws IllegalArgumentException
175     {
176         try {
177             return _method.invoke(pojo, (Object[]) null);
178         } catch (IllegalAccessException | InvocationTargetException e) {
179             throw new IllegalArgumentException("Failed to getValue() with method "
180                     +getFullName()+": "+e.getMessage(), e);
181         }
182     }
183 
184     /*
185     /*****************************************************
186     /* Extended API, generic
187     /*****************************************************
188      */
189 
190     @Override
getFullName()191     public String getFullName() {
192         final String methodName = super.getFullName();
193         switch (getParameterCount()) {
194         case 0:
195             return methodName+"()";
196         case 1:
197             return methodName+"("+getRawParameterType(0).getName()+")";
198         default:
199         }
200         return String.format("%s(%d params)", super.getFullName(), getParameterCount());
201     }
202 
getRawParameterTypes()203     public Class<?>[] getRawParameterTypes()
204     {
205         if (_paramClasses == null) {
206             _paramClasses = _method.getParameterTypes();
207         }
208         return _paramClasses;
209     }
210 
211     @Deprecated // since 2.7
getGenericParameterTypes()212     public Type[] getGenericParameterTypes() {
213         return _method.getGenericParameterTypes();
214     }
215 
getRawReturnType()216     public Class<?> getRawReturnType() {
217         return _method.getReturnType();
218     }
219 
220     /**
221      * Helper method that can be used to check whether method returns
222      * a value or not; if return type declared as <code>void</code>, returns
223      * false, otherwise true
224      *
225      * @since 2.4
226      *
227      * @deprecated Since 2.12 (related to [databind#2675]), needs to be configurable
228      */
229     @Deprecated
hasReturnType()230     public boolean hasReturnType() {
231         Class<?> rt = getRawReturnType();
232         // also, as per [databind#2675], only consider `void` to be real "No return type"
233         return (rt != Void.TYPE);
234     }
235 
236     /*
237     /********************************************************
238     /* Other
239     /********************************************************
240      */
241 
242     @Override
toString()243     public String toString() {
244         return "[method "+getFullName()+"]";
245     }
246 
247     @Override
hashCode()248     public int hashCode() {
249         return _method.getName().hashCode();
250     }
251 
252     @Override
equals(Object o)253     public boolean equals(Object o) {
254         if (o == this) return true;
255         return ClassUtil.hasClass(o, getClass())
256                 && (((AnnotatedMethod) o)._method == _method);
257     }
258 
259     /*
260     /**********************************************************
261     /* JDK serialization handling
262     /**********************************************************
263      */
264 
writeReplace()265     Object writeReplace() {
266         return new AnnotatedMethod(new Serialization(_method));
267     }
268 
readResolve()269     Object readResolve() {
270         Class<?> clazz = _serialization.clazz;
271         try {
272             Method m = clazz.getDeclaredMethod(_serialization.name,
273                     _serialization.args);
274             // 06-Oct-2012, tatu: Has "lost" its security override, may need to force back
275             if (!m.isAccessible()) {
276                 ClassUtil.checkAndFixAccess(m, false);
277             }
278             return new AnnotatedMethod(null, m, null, null);
279         } catch (Exception e) {
280             throw new IllegalArgumentException("Could not find method '"+_serialization.name
281                         +"' from Class '"+clazz.getName());
282         }
283     }
284 
285     /**
286      * Helper class that is used as the workaround to persist
287      * Field references. It basically just stores declaring class
288      * and field name.
289      */
290     private final static class Serialization
291         implements java.io.Serializable
292     {
293         private static final long serialVersionUID = 1L;
294         protected Class<?> clazz;
295         protected String name;
296         protected Class<?>[] args;
297 
Serialization(Method setter)298         public Serialization(Method setter) {
299             clazz = setter.getDeclaringClass();
300             name = setter.getName();
301             args = setter.getParameterTypes();
302         }
303     }
304 }
305