1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.property;
26
27 import java.lang.reflect.Field;
28 import java.lang.reflect.Method;
29 import java.util.Map;
30
31 import org.hibernate.HibernateException;
32 import org.hibernate.PropertyAccessException;
33 import org.hibernate.PropertyNotFoundException;
34 import org.hibernate.engine.SessionFactoryImplementor;
35 import org.hibernate.engine.SessionImplementor;
36 import org.hibernate.util.ReflectHelper;
37
38 /**
39 * Accesses fields directly.
40 * @author Gavin King
41 */
42 public class DirectPropertyAccessor implements PropertyAccessor {
43
44 public static final class DirectGetter implements Getter {
45 private final transient Field field;
46 private final Class clazz;
47 private final String name;
48 DirectGetter(Field field, Class clazz, String name) {
49 this.field = field;
50 this.clazz = clazz;
51 this.name = name;
52 }
53 public Object get(Object target) throws HibernateException {
54 try {
55 return field.get(target);
56 }
57 catch (Exception e) {
58 throw new PropertyAccessException(e, "could not get a field value by reflection", false, clazz, name);
59 }
60 }
61
62 public Object getForInsert(Object target, Map mergeMap, SessionImplementor session) {
63 return get( target );
64 }
65
66 public Method getMethod() {
67 return null;
68 }
69 public String getMethodName() {
70 return null;
71 }
72 public Class getReturnType() {
73 return field.getType();
74 }
75
76 Object readResolve() {
77 return new DirectGetter( getField(clazz, name), clazz, name );
78 }
79
80 public String toString() {
81 return "DirectGetter(" + clazz.getName() + '.' + name + ')';
82 }
83 }
84
85 public static final class DirectSetter implements Setter {
86 private final transient Field field;
87 private final Class clazz;
88 private final String name;
89 DirectSetter(Field field, Class clazz, String name) {
90 this.field = field;
91 this.clazz = clazz;
92 this.name = name;
93 }
94 public Method getMethod() {
95 return null;
96 }
97 public String getMethodName() {
98 return null;
99 }
100 public void set(Object target, Object value, SessionFactoryImplementor factory) throws HibernateException {
101 try {
102 field.set(target, value);
103 }
104 catch (Exception e) {
105 if(value == null && field.getType().isPrimitive()) {
106 throw new PropertyAccessException(
107 e,
108 "Null value was assigned to a property of primitive type",
109 true,
110 clazz,
111 name
112 );
113 } else {
114 throw new PropertyAccessException(e, "could not set a field value by reflection", true, clazz, name);
115 }
116 }
117 }
118
119 public String toString() {
120 return "DirectSetter(" + clazz.getName() + '.' + name + ')';
121 }
122
123 Object readResolve() {
124 return new DirectSetter( getField(clazz, name), clazz, name );
125 }
126 }
127
128 private static Field getField(Class clazz, String name) throws PropertyNotFoundException {
129 if ( clazz==null || clazz==Object.class ) {
130 throw new PropertyNotFoundException("field not found: " + name);
131 }
132 Field field;
133 try {
134 field = clazz.getDeclaredField(name);
135 }
136 catch (NoSuchFieldException nsfe) {
137 field = getField( clazz, clazz.getSuperclass(), name );
138 }
139 if ( !ReflectHelper.isPublic(clazz, field) ) field.setAccessible(true);
140 return field;
141 }
142
143 private static Field getField(Class root, Class clazz, String name) throws PropertyNotFoundException {
144 if ( clazz==null || clazz==Object.class ) {
145 throw new PropertyNotFoundException("field [" + name + "] not found on " + root.getName());
146 }
147 Field field;
148 try {
149 field = clazz.getDeclaredField(name);
150 }
151 catch (NoSuchFieldException nsfe) {
152 field = getField( root, clazz.getSuperclass(), name );
153 }
154 if ( !ReflectHelper.isPublic(clazz, field) ) field.setAccessible(true);
155 return field;
156 }
157
158 public Getter getGetter(Class theClass, String propertyName)
159 throws PropertyNotFoundException {
160 return new DirectGetter( getField(theClass, propertyName), theClass, propertyName );
161 }
162
163 public Setter getSetter(Class theClass, String propertyName)
164 throws PropertyNotFoundException {
165 return new DirectSetter( getField(theClass, propertyName), theClass, propertyName );
166 }
167
168 }