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 /**
9  * Object that represents non-static (and usually non-transient/volatile)
10  * fields of a class.
11  */

12 public final class AnnotatedField
13     extends AnnotatedMember
14     implements java.io.Serializable
15 {
16     private static final long serialVersionUID = 1L;
17
18     /**
19      * Actual {@link Field} used for access.
20      *<p>
21      * Transient since it cannot be persisted directly using
22      * JDK serialization
23      */

24     protected final transient Field _field;
25
26     /**
27      * Temporary field required for JDK serialization support
28      */

29     protected Serialization _serialization;
30
31     /*
32     /**********************************************************
33     /* Life-cycle
34     /**********************************************************
35      */

36
37     public AnnotatedField(TypeResolutionContext contextClass, Field field, AnnotationMap annMap)
38     {
39         super(contextClass, annMap);
40         _field = field;
41     }
42     
43     @Override
44     public AnnotatedField withAnnotations(AnnotationMap ann) {
45         return new AnnotatedField(_typeContext, _field, ann);
46     }
47
48     /**
49      * Method used for JDK serialization support
50      */

51     protected AnnotatedField(Serialization ser)
52     {
53         super(nullnull);
54         _field = null;
55         _serialization = ser;
56     }
57     
58     /*
59     /**********************************************************
60     /* Annotated impl
61     /**********************************************************
62      */

63
64     @Override
65     public Field getAnnotated() { return _field; }
66
67     @Override
68     public int getModifiers() { return _field.getModifiers(); }
69
70     @Override
71     public String getName() { return _field.getName(); }
72
73     @Override
74     public Class<?> getRawType() {
75         return _field.getType();
76     }
77
78     @Override
79     public JavaType getType() {
80         return _typeContext.resolveType(_field.getGenericType());
81     }
82
83     /*
84     /**********************************************************
85     /* AnnotatedMember impl
86     /**********************************************************
87      */

88
89     @Override
90     public Class<?> getDeclaringClass() { return _field.getDeclaringClass(); }
91
92     @Override
93     public Member getMember() { return _field; }
94
95     @Override
96     public void setValue(Object pojo, Object value) throws IllegalArgumentException
97     {
98         try {
99             _field.set(pojo, value);
100         } catch (IllegalAccessException e) {
101             throw new IllegalArgumentException("Failed to setValue() for field "
102                     +getFullName()+": "+e.getMessage(), e);
103         }
104     }
105
106     @Override
107     public Object getValue(Object pojo) throws IllegalArgumentException
108     {
109         try {
110             return _field.get(pojo);
111         } catch (IllegalAccessException e) {
112             throw new IllegalArgumentException("Failed to getValue() for field "
113                     +getFullName()+": "+e.getMessage(), e);
114         }
115     }
116     
117     /*
118     /**********************************************************
119     /* Extended API, generic
120     /**********************************************************
121      */

122
123     public int getAnnotationCount() { return _annotations.size(); }
124
125     /**
126      * @since 2.6
127      */

128     public boolean isTransient() { return Modifier.isTransient(getModifiers()); }
129     
130     @Override
131     public int hashCode() {
132         return _field.getName().hashCode();
133     }
134     
135     @Override
136     public boolean equals(Object o) {
137         if (o == thisreturn true;
138         return ClassUtil.hasClass(o, getClass())
139                 && (((AnnotatedField) o)._field == _field);
140     }
141
142     @Override
143     public String toString() {
144         return "[field "+getFullName()+"]";
145     }
146
147     /*
148     /**********************************************************
149     /* JDK serialization handling
150     /**********************************************************
151      */

152
153     Object writeReplace() {
154         return new AnnotatedField(new Serialization(_field));
155     }
156
157     Object readResolve() {
158         Class<?> clazz = _serialization.clazz;
159         try {
160             Field f = clazz.getDeclaredField(_serialization.name);
161             // 06-Oct-2012, tatu: Has "lost" its security override, may need to force back
162             if (!f.isAccessible()) {
163                 ClassUtil.checkAndFixAccess(f, false);
164             }
165             return new AnnotatedField(null, f, null);
166         } catch (Exception e) {
167             throw new IllegalArgumentException("Could not find method '"+_serialization.name
168                         +"' from Class '"+clazz.getName());
169         }
170     }
171     
172     /**
173      * Helper class that is used as the workaround to persist
174      * Field references. It basically just stores declaring class
175      * and field name.
176      */

177     private final static class Serialization
178         implements java.io.Serializable
179     {
180         private static final long serialVersionUID = 1L;
181         protected Class<?> clazz;
182         protected String name;
183
184         public Serialization(Field f) {
185             clazz = f.getDeclaringClass();
186             name = f.getName();
187             
188         }
189     }
190 }
191
192