1
10
11 package com.sun.xml.bind.v2.runtime.reflect;
12
13 import java.lang.reflect.Field;
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.lang.reflect.Modifier;
17 import java.lang.reflect.Type;
18 import java.util.Arrays;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24
25 import javax.xml.bind.JAXBElement;
26 import javax.xml.bind.annotation.adapters.XmlAdapter;
27
28 import com.sun.istack.Nullable;
29 import com.sun.xml.bind.api.AccessorException;
30 import com.sun.xml.bind.api.JAXBRIContext;
31 import com.sun.xml.bind.v2.model.core.Adapter;
32 import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder;
33 import com.sun.xml.bind.v2.runtime.JAXBContextImpl;
34 import com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory;
35 import com.sun.xml.bind.v2.runtime.unmarshaller.Loader;
36 import com.sun.xml.bind.v2.runtime.unmarshaller.Receiver;
37 import com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext;
38
39 import org.xml.sax.SAXException;
40
41
57 public abstract class Accessor<BeanT, ValueT> implements Receiver {
58
59 public final Class<ValueT> valueType;
60
61 public Class<ValueT> getValueType() {
62 return valueType;
63 }
64
65 protected Accessor(Class<ValueT> valueType) {
66 this.valueType = valueType;
67 }
68
69
76 public Accessor<BeanT, ValueT> optimize(@Nullable JAXBContextImpl context) {
77 return this;
78 }
79
80
81
89 public abstract ValueT get(BeanT bean) throws AccessorException;
90
91
101 public abstract void set(BeanT bean, ValueT value) throws AccessorException;
102
103
104
110 public Object getUnadapted(BeanT bean) throws AccessorException {
111 return get(bean);
112 }
113
114
119 public boolean isAdapted() {
120 return false;
121 }
122
123
129 public void setUnadapted(BeanT bean, Object value) throws AccessorException {
130 set(bean, (ValueT) value);
131 }
132
133 public void receive(UnmarshallingContext.State state, Object o) throws SAXException {
134 try {
135 set((BeanT) state.getTarget(), (ValueT) o);
136 } catch (AccessorException e) {
137 Loader.handleGenericException(e, true);
138 } catch (IllegalAccessError iae) {
139
140 Loader.handleGenericError(iae);
141 }
142 }
143
144 private static List<Class> nonAbstractableClasses = Arrays.asList(new Class[]{
145 Object.class,
146 java.util.Calendar.class,
147 javax.xml.datatype.Duration.class,
148 javax.xml.datatype.XMLGregorianCalendar.class,
149 java.awt.Image.class,
150 javax.activation.DataHandler.class,
151 javax.xml.transform.Source.class,
152 java.util.Date.class,
153 java.io.File.class,
154 java.net.URI.class,
155 java.net.URL.class,
156 Class.class,
157 String.class,
158 javax.xml.transform.Source.class}
159 );
160
161 public boolean isValueTypeAbstractable() {
162 return !nonAbstractableClasses.contains(getValueType());
163 }
164
165
170 public boolean isAbstractable(Class clazz) {
171 return !nonAbstractableClasses.contains(clazz);
172 }
173
174
178 public final <T> Accessor<BeanT, T> adapt(Class<T> targetType, final Class<? extends XmlAdapter<T, ValueT>> adapter) {
179 return new AdaptedAccessor<BeanT, ValueT, T>(targetType, this, adapter);
180 }
181
182 public final <T> Accessor<BeanT, T> adapt(Adapter<Type, Class> adapter) {
183 return new AdaptedAccessor<BeanT, ValueT, T>(
184 (Class<T>) Utils.REFLECTION_NAVIGATOR.erasure(adapter.defaultType),
185 this,
186 adapter.adapterType);
187 }
188
189
193 private static boolean accessWarned = false;
194
195
196
199 public static class FieldReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
200 public final Field f;
201
202 private static final Logger logger = com.sun.xml.bind.Utils.getClassLogger();
203
204 public FieldReflection(Field f) {
205 this(f, false);
206 }
207
208 public FieldReflection(Field f, boolean supressAccessorWarnings) {
209 super((Class<ValueT>) f.getType());
210 this.f = f;
211
212 int mod = f.getModifiers();
213 if (!Modifier.isPublic(mod) || Modifier.isFinal(mod) || !Modifier.isPublic(f.getDeclaringClass().getModifiers())) {
214 try {
215
216
217 f.setAccessible(true);
218 } catch (SecurityException e) {
219 if ((!accessWarned) && (!supressAccessorWarnings)) {
220
221 logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
222 f.getDeclaringClass().getName(),
223 f.getName()),
224 e);
225 }
226 accessWarned = true;
227 }
228 }
229 }
230
231 public ValueT get(BeanT bean) {
232 try {
233 return (ValueT) f.get(bean);
234 } catch (IllegalAccessException e) {
235 throw new IllegalAccessError(e.getMessage());
236 }
237 }
238
239 public void set(BeanT bean, ValueT value) {
240 try {
241 if (value == null)
242 value = (ValueT) uninitializedValues.get(valueType);
243 f.set(bean, value);
244 } catch (IllegalAccessException e) {
245 throw new IllegalAccessError(e.getMessage());
246 }
247 }
248
249 @Override
250 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
251 if (context != null && context.fastBoot) {
252
253 return this;
254 }
255 Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(f);
256 if (acc != null) {
257 return acc;
258 }
259 return this;
260 }
261 }
262
263
266 public static final class ReadOnlyFieldReflection<BeanT, ValueT> extends FieldReflection<BeanT, ValueT> {
267 public ReadOnlyFieldReflection(Field f, boolean supressAccessorWarnings) {
268 super(f, supressAccessorWarnings);
269 }
270 public ReadOnlyFieldReflection(Field f) {
271 super(f);
272 }
273
274 @Override
275 public void set(BeanT bean, ValueT value) {
276
277 }
278
279 @Override
280 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
281 return this;
282 }
283 }
284
285
286
289 public static class GetterSetterReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
290 public final Method getter;
291 public final Method setter;
292
293 private static final Logger logger = com.sun.xml.bind.Utils.getClassLogger();
294
295 public GetterSetterReflection(Method getter, Method setter) {
296 super(
297 (Class<ValueT>) (getter != null ?
298 getter.getReturnType() :
299 setter.getParameterTypes()[0]));
300 this.getter = getter;
301 this.setter = setter;
302
303 if (getter != null)
304 makeAccessible(getter);
305 if (setter != null)
306 makeAccessible(setter);
307 }
308
309 private void makeAccessible(Method m) {
310 if (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
311 try {
312 m.setAccessible(true);
313 } catch (SecurityException e) {
314 if (!accessWarned)
315
316 logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
317 m.getDeclaringClass().getName(),
318 m.getName()),
319 e);
320 accessWarned = true;
321 }
322 }
323 }
324
325 public ValueT get(BeanT bean) throws AccessorException {
326 try {
327 return (ValueT) getter.invoke(bean);
328 } catch (IllegalAccessException e) {
329 throw new IllegalAccessError(e.getMessage());
330 } catch (InvocationTargetException e) {
331 throw handleInvocationTargetException(e);
332 }
333 }
334
335 public void set(BeanT bean, ValueT value) throws AccessorException {
336 try {
337 if (value == null)
338 value = (ValueT) uninitializedValues.get(valueType);
339 setter.invoke(bean, value);
340 } catch (IllegalAccessException e) {
341 throw new IllegalAccessError(e.getMessage());
342 } catch (InvocationTargetException e) {
343 throw handleInvocationTargetException(e);
344 }
345 }
346
347 private AccessorException handleInvocationTargetException(InvocationTargetException e) {
348
349 Throwable t = e.getTargetException();
350 if (t instanceof RuntimeException)
351 throw (RuntimeException) t;
352 if (t instanceof Error)
353 throw (Error) t;
354
355
356
357
358
359
360 return new AccessorException(t);
361 }
362
363 @Override
364 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
365 if (getter == null || setter == null) {
366
367 return this;
368 }
369 if (context != null && context.fastBoot) {
370
371 return this;
372 }
373
374 Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(getter, setter);
375 if (acc != null) {
376 return acc;
377 }
378
379 return this;
380 }
381 }
382
383
389 public static class GetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
390 public GetterOnlyReflection(Method getter) {
391 super(getter, null);
392 }
393
394 @Override
395 public void set(BeanT bean, ValueT value) throws AccessorException {
396 throw new AccessorException(Messages.NO_SETTER.format(getter.toString()));
397 }
398 }
399
400
406 public static class SetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
407 public SetterOnlyReflection(Method setter) {
408 super(null, setter);
409 }
410
411 @Override
412 public ValueT get(BeanT bean) throws AccessorException {
413 throw new AccessorException(Messages.NO_GETTER.format(setter.toString()));
414 }
415 }
416
417
420 @SuppressWarnings("unchecked")
421 public static <A, B> Accessor<A, B> getErrorInstance() {
422 return ERROR;
423 }
424
425 private static final Accessor ERROR = new Accessor<Object, Object>(Object.class) {
426 public Object get(Object o) {
427 return null;
428 }
429
430 public void set(Object o, Object o1) {
431 }
432 };
433
434
437 public static final Accessor<JAXBElement, Object> JAXB_ELEMENT_VALUE = new Accessor<JAXBElement, Object>(Object.class) {
438 public Object get(JAXBElement jaxbElement) {
439 return jaxbElement.getValue();
440 }
441
442 public void set(JAXBElement jaxbElement, Object o) {
443 jaxbElement.setValue(o);
444 }
445 };
446
447
450 private static final Map<Class, Object> uninitializedValues = new HashMap<Class, Object>();
451
452 static {
453
463 uninitializedValues.put(byte.class, Byte.valueOf((byte) 0));
464 uninitializedValues.put(boolean.class, false);
465 uninitializedValues.put(char.class, Character.valueOf((char) 0));
466 uninitializedValues.put(float.class, Float.valueOf(0));
467 uninitializedValues.put(double.class, Double.valueOf(0));
468 uninitializedValues.put(int.class, Integer.valueOf(0));
469 uninitializedValues.put(long.class, Long.valueOf(0));
470 uninitializedValues.put(short.class, Short.valueOf((short) 0));
471 }
472
473 }
474