Sun, 18 Jun 2017 23:18:45 +0100
8172297: In java 8, the marshalling with JAX-WS does not escape carriage return
Reviewed-by: lancea
1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.bind.v2.runtime.reflect;
28 import java.lang.reflect.Field;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 import java.lang.reflect.Type;
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.logging.Level;
38 import java.util.logging.Logger;
40 import javax.xml.bind.JAXBElement;
41 import javax.xml.bind.annotation.adapters.XmlAdapter;
43 import com.sun.istack.internal.Nullable;
44 import com.sun.xml.internal.bind.Util;
45 import com.sun.xml.internal.bind.api.AccessorException;
46 import com.sun.xml.internal.bind.api.JAXBRIContext;
47 import com.sun.xml.internal.bind.v2.model.core.Adapter;
48 import com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder;
49 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
50 import com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory;
51 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
52 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
53 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
55 import org.xml.sax.SAXException;
57 /**
58 * Accesses a particular property of a bean.
59 * <p/>
60 * <p/>
61 * This interface encapsulates the access to the actual data store.
62 * The intention is to generate implementations for a particular bean
63 * and a property to improve the performance.
64 * <p/>
65 * <p/>
66 * Accessor can be used as a receiver. Upon receiving an object
67 * it sets that to the field.
68 *
69 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
70 * @see Accessor.FieldReflection
71 * @see TransducedAccessor
72 */
73 public abstract class Accessor<BeanT, ValueT> implements Receiver {
75 public final Class<ValueT> valueType;
77 public Class<ValueT> getValueType() {
78 return valueType;
79 }
81 protected Accessor(Class<ValueT> valueType) {
82 this.valueType = valueType;
83 }
85 /**
86 * Returns the optimized version of the same accessor.
87 *
88 * @param context The {@link JAXBContextImpl} that owns the whole thing.
89 * (See {@link RuntimeModelBuilder#context}.)
90 * @return At least the implementation can return <tt>this</tt>.
91 */
92 public Accessor<BeanT, ValueT> optimize(@Nullable JAXBContextImpl context) {
93 return this;
94 }
97 /**
98 * Gets the value of the property of the given bean object.
99 *
100 * @param bean must not be null.
101 * @throws AccessorException if failed to set a value. For example, the getter method
102 * may throw an exception.
103 * @since 2.0 EA1
104 */
105 public abstract ValueT get(BeanT bean) throws AccessorException;
107 /**
108 * Sets the value of the property of the given bean object.
109 *
110 * @param bean must not be null.
111 * @param value the value to be set. Setting value to null means resetting
112 * to the VM default value (even for primitive properties.)
113 * @throws AccessorException if failed to set a value. For example, the setter method
114 * may throw an exception.
115 * @since 2.0 EA1
116 */
117 public abstract void set(BeanT bean, ValueT value) throws AccessorException;
120 /**
121 * Sets the value without adapting the value.
122 * <p/>
123 * This ugly entry point is only used by JAX-WS.
124 * See {@link JAXBRIContext#getElementPropertyAccessor}
125 */
126 public Object getUnadapted(BeanT bean) throws AccessorException {
127 return get(bean);
128 }
130 /**
131 * Returns true if this accessor wraps an adapter.
132 * <p/>
133 * This method needs to be used with care, but it helps some optimization.
134 */
135 public boolean isAdapted() {
136 return false;
137 }
139 /**
140 * Sets the value without adapting the value.
141 * <p/>
142 * This ugly entry point is only used by JAX-WS.
143 * See {@link JAXBRIContext#getElementPropertyAccessor}
144 */
145 public void setUnadapted(BeanT bean, Object value) throws AccessorException {
146 set(bean, (ValueT) value);
147 }
149 public void receive(UnmarshallingContext.State state, Object o) throws SAXException {
150 try {
151 set((BeanT) state.getTarget(), (ValueT) o);
152 } catch (AccessorException e) {
153 Loader.handleGenericException(e, true);
154 } catch (IllegalAccessError iae) {
155 // throw UnmarshalException instead IllegalAccesssError | Issue 475
156 Loader.handleGenericError(iae);
157 }
158 }
160 private static List<Class> nonAbstractableClasses = Arrays.asList(new Class[]{
161 Object.class,
162 java.util.Calendar.class,
163 javax.xml.datatype.Duration.class,
164 javax.xml.datatype.XMLGregorianCalendar.class,
165 java.awt.Image.class,
166 javax.activation.DataHandler.class,
167 javax.xml.transform.Source.class,
168 java.util.Date.class,
169 java.io.File.class,
170 java.net.URI.class,
171 java.net.URL.class,
172 Class.class,
173 String.class,
174 javax.xml.transform.Source.class}
175 );
177 public boolean isValueTypeAbstractable() {
178 return !nonAbstractableClasses.contains(getValueType());
179 }
181 /**
182 * Checks if it is not builtin jaxb class
183 * @param clazz to be checked
184 * @return true if it is NOT builtin class
185 */
186 public boolean isAbstractable(Class clazz) {
187 return !nonAbstractableClasses.contains(clazz);
188 }
190 /**
191 * Wraps this {@link Accessor} into another {@link Accessor}
192 * and performs the type adaption as necessary.
193 */
194 public final <T> Accessor<BeanT, T> adapt(Class<T> targetType, final Class<? extends XmlAdapter<T, ValueT>> adapter) {
195 return new AdaptedAccessor<BeanT, ValueT, T>(targetType, this, adapter);
196 }
198 public final <T> Accessor<BeanT, T> adapt(Adapter<Type, Class> adapter) {
199 return new AdaptedAccessor<BeanT, ValueT, T>(
200 (Class<T>) Utils.REFLECTION_NAVIGATOR.erasure(adapter.defaultType),
201 this,
202 adapter.adapterType);
203 }
205 /**
206 * Flag that will be set to true after issueing a warning
207 * about the lack of permission to access non-public fields.
208 */
209 private static boolean accessWarned = false;
212 /**
213 * {@link Accessor} that uses Java reflection to access a field.
214 */
215 public static class FieldReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
216 public final Field f;
218 private static final Logger logger = Util.getClassLogger();
220 public FieldReflection(Field f) {
221 this(f, false);
222 }
224 public FieldReflection(Field f, boolean supressAccessorWarnings) {
225 super((Class<ValueT>) f.getType());
226 this.f = f;
228 int mod = f.getModifiers();
229 if (!Modifier.isPublic(mod) || Modifier.isFinal(mod) || !Modifier.isPublic(f.getDeclaringClass().getModifiers())) {
230 try {
231 // attempt to make it accessible, but do so in the security context of the calling application.
232 // don't do this in the doPrivilege block, as that would create a security hole for anyone
233 // to make any field accessible.
234 f.setAccessible(true);
235 } catch (SecurityException e) {
236 if ((!accessWarned) && (!supressAccessorWarnings)) {
237 // this happens when we don't have enough permission.
238 logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
239 f.getDeclaringClass().getName(),
240 f.getName()),
241 e);
242 }
243 accessWarned = true;
244 }
245 }
246 }
248 public ValueT get(BeanT bean) {
249 try {
250 return (ValueT) f.get(bean);
251 } catch (IllegalAccessException e) {
252 throw new IllegalAccessError(e.getMessage());
253 }
254 }
256 public void set(BeanT bean, ValueT value) {
257 try {
258 if (value == null)
259 value = (ValueT) uninitializedValues.get(valueType);
260 f.set(bean, value);
261 } catch (IllegalAccessException e) {
262 throw new IllegalAccessError(e.getMessage());
263 }
264 }
266 @Override
267 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
268 if (context != null && context.fastBoot)
269 // let's not waste time on doing this for the sake of faster boot.
270 return this;
271 Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(f);
272 if (acc != null)
273 return acc;
274 else
275 return this;
276 }
277 }
279 /**
280 * Read-only access to {@link Field}. Used to handle a static field.
281 */
282 public static final class ReadOnlyFieldReflection<BeanT, ValueT> extends FieldReflection<BeanT, ValueT> {
283 public ReadOnlyFieldReflection(Field f, boolean supressAccessorWarnings) {
284 super(f, supressAccessorWarnings);
285 }
286 public ReadOnlyFieldReflection(Field f) {
287 super(f);
288 }
290 @Override
291 public void set(BeanT bean, ValueT value) {
292 // noop
293 }
295 @Override
296 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
297 return this;
298 }
299 }
302 /**
303 * {@link Accessor} that uses Java reflection to access a getter and a setter.
304 */
305 public static class GetterSetterReflection<BeanT, ValueT> extends Accessor<BeanT, ValueT> {
306 public final Method getter;
307 public final Method setter;
309 private static final Logger logger = Util.getClassLogger();
311 public GetterSetterReflection(Method getter, Method setter) {
312 super(
313 (Class<ValueT>) (getter != null ?
314 getter.getReturnType() :
315 setter.getParameterTypes()[0]));
316 this.getter = getter;
317 this.setter = setter;
319 if (getter != null)
320 makeAccessible(getter);
321 if (setter != null)
322 makeAccessible(setter);
323 }
325 private void makeAccessible(Method m) {
326 if (!Modifier.isPublic(m.getModifiers()) || !Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
327 try {
328 m.setAccessible(true);
329 } catch (SecurityException e) {
330 if (!accessWarned)
331 // this happens when we don't have enough permission.
332 logger.log(Level.WARNING, Messages.UNABLE_TO_ACCESS_NON_PUBLIC_FIELD.format(
333 m.getDeclaringClass().getName(),
334 m.getName()),
335 e);
336 accessWarned = true;
337 }
338 }
339 }
341 public ValueT get(BeanT bean) throws AccessorException {
342 try {
343 return (ValueT) getter.invoke(bean);
344 } catch (IllegalAccessException e) {
345 throw new IllegalAccessError(e.getMessage());
346 } catch (InvocationTargetException e) {
347 throw handleInvocationTargetException(e);
348 }
349 }
351 public void set(BeanT bean, ValueT value) throws AccessorException {
352 try {
353 if (value == null)
354 value = (ValueT) uninitializedValues.get(valueType);
355 setter.invoke(bean, value);
356 } catch (IllegalAccessException e) {
357 throw new IllegalAccessError(e.getMessage());
358 } catch (InvocationTargetException e) {
359 throw handleInvocationTargetException(e);
360 }
361 }
363 private AccessorException handleInvocationTargetException(InvocationTargetException e) {
364 // don't block a problem in the user code
365 Throwable t = e.getTargetException();
366 if (t instanceof RuntimeException)
367 throw (RuntimeException) t;
368 if (t instanceof Error)
369 throw (Error) t;
371 // otherwise it's a checked exception.
372 // I'm not sure how to handle this.
373 // we can throw a checked exception from here,
374 // but because get/set would be called from so many different places,
375 // the handling would be tedious.
376 return new AccessorException(t);
377 }
379 @Override
380 public Accessor<BeanT, ValueT> optimize(JAXBContextImpl context) {
381 if (getter == null || setter == null)
382 // if we aren't complete, OptimizedAccessor won't always work
383 return this;
384 if (context != null && context.fastBoot)
385 // let's not waste time on doing this for the sake of faster boot.
386 return this;
388 Accessor<BeanT, ValueT> acc = OptimizedAccessorFactory.get(getter, setter);
389 if (acc != null)
390 return acc;
391 else
392 return this;
393 }
394 }
396 /**
397 * A version of {@link GetterSetterReflection} that doesn't have any setter.
398 * <p/>
399 * <p/>
400 * This provides a user-friendly error message.
401 */
402 public static class GetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
403 public GetterOnlyReflection(Method getter) {
404 super(getter, null);
405 }
407 @Override
408 public void set(BeanT bean, ValueT value) throws AccessorException {
409 throw new AccessorException(Messages.NO_SETTER.format(getter.toString()));
410 }
411 }
413 /**
414 * A version of {@link GetterSetterReflection} thaat doesn't have any getter.
415 * <p/>
416 * <p/>
417 * This provides a user-friendly error message.
418 */
419 public static class SetterOnlyReflection<BeanT, ValueT> extends GetterSetterReflection<BeanT, ValueT> {
420 public SetterOnlyReflection(Method setter) {
421 super(null, setter);
422 }
424 @Override
425 public ValueT get(BeanT bean) throws AccessorException {
426 throw new AccessorException(Messages.NO_GETTER.format(setter.toString()));
427 }
428 }
430 /**
431 * Gets the special {@link Accessor} used to recover from errors.
432 */
433 @SuppressWarnings("unchecked")
434 public static <A, B> Accessor<A, B> getErrorInstance() {
435 return ERROR;
436 }
438 private static final Accessor ERROR = new Accessor<Object, Object>(Object.class) {
439 public Object get(Object o) {
440 return null;
441 }
443 public void set(Object o, Object o1) {
444 }
445 };
447 /**
448 * {@link Accessor} for {@link JAXBElement#getValue()}.
449 */
450 public static final Accessor<JAXBElement, Object> JAXB_ELEMENT_VALUE = new Accessor<JAXBElement, Object>(Object.class) {
451 public Object get(JAXBElement jaxbElement) {
452 return jaxbElement.getValue();
453 }
455 public void set(JAXBElement jaxbElement, Object o) {
456 jaxbElement.setValue(o);
457 }
458 };
460 /**
461 * Uninitialized map keyed by their classes.
462 */
463 private static final Map<Class, Object> uninitializedValues = new HashMap<Class, Object>();
465 static {
466 /*
467 static byte default_value_byte = 0;
468 static boolean default_value_boolean = false;
469 static char default_value_char = 0;
470 static float default_value_float = 0;
471 static double default_value_double = 0;
472 static int default_value_int = 0;
473 static long default_value_long = 0;
474 static short default_value_short = 0;
475 */
476 uninitializedValues.put(byte.class, Byte.valueOf((byte) 0));
477 uninitializedValues.put(boolean.class, false);
478 uninitializedValues.put(char.class, Character.valueOf((char) 0));
479 uninitializedValues.put(float.class, Float.valueOf(0));
480 uninitializedValues.put(double.class, Double.valueOf(0));
481 uninitializedValues.put(int.class, Integer.valueOf(0));
482 uninitializedValues.put(long.class, Long.valueOf(0));
483 uninitializedValues.put(short.class, Short.valueOf((short) 0));
484 }
486 }