1 /*
2 * Copyright (c) 1997, 2013, 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
28 import java.lang.reflect.Array;
29 import java.lang.reflect.Field;
30 import java.lang.reflect.GenericArrayType;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.ParameterizedType;
33 import java.lang.reflect.Type;
34 import java.security.AccessController;
35 import java.security.PrivilegedActionException;
36 import java.security.PrivilegedExceptionAction;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42
43 import javax.xml.bind.JAXBElement;
44 import javax.xml.bind.annotation.XmlElement;
45 import javax.xml.bind.annotation.XmlElementRef;
46 import javax.xml.bind.annotation.XmlElementWrapper;
47 import javax.xml.namespace.QName;
48
49 /**
50 * JAXBWrapperAccessor
51 *
52 * @author shih-chang.chen@oracle.com
53 */
54 @SuppressWarnings({ "unchecked", "rawtypes" })
55 public class JAXBWrapperAccessor extends WrapperAccessor {
56
57 protected Class<?> contentClass;
58 protected HashMap<Object, Class> elementDeclaredTypes;
59
60 public JAXBWrapperAccessor(Class<?> wrapperBean) {
61 contentClass = (Class<?>) wrapperBean;
62
63 HashMap<Object, PropertySetter> setByQName = new HashMap<Object, PropertySetter>();
64 HashMap<Object, PropertySetter> setByLocalpart = new HashMap<Object, PropertySetter>();
65 HashMap<String, Method> publicSetters = new HashMap<String, Method>();
66
67 HashMap<Object, PropertyGetter> getByQName = new HashMap<Object, PropertyGetter>();
68 HashMap<Object, PropertyGetter> getByLocalpart = new HashMap<Object, PropertyGetter>();
69 HashMap<String, Method> publicGetters = new HashMap<String, Method>();
70
71 HashMap<Object, Class> elementDeclaredTypesByQName = new HashMap<Object, Class>();
72 HashMap<Object, Class> elementDeclaredTypesByLocalpart = new HashMap<Object, Class>();
73
74 for (Method method : contentClass.getMethods()) {
75 if (PropertySetterBase.setterPattern(method)) {
76 String key = method.getName()
77 .substring(3, method.getName().length()).toLowerCase();
78 publicSetters.put(key, method);
79 }
80 if (PropertyGetterBase.getterPattern(method)) {
125 Type arg = ((ParameterizedType) field.getGenericType())
126 .getActualTypeArguments()[0];
127 if (arg instanceof Class) {
128 elementDeclaredTypesByQName.put(qname, (Class) arg);
129 elementDeclaredTypesByLocalpart.put(localName,
130 (Class) arg);
131 } else if (arg instanceof GenericArrayType) {
132 Type componentType = ((GenericArrayType) arg)
133 .getGenericComponentType();
134 if (componentType instanceof Class) {
135 Class arrayClass = Array.newInstance(
136 (Class) componentType, 0).getClass();
137 elementDeclaredTypesByQName.put(qname, arrayClass);
138 elementDeclaredTypesByLocalpart.put(localName,
139 arrayClass);
140 }
141 }
142 }
143
144 }
145 // _return
146 if (fieldName.startsWith("_") && !localName.startsWith("_")) {
147 fieldName = fieldName.substring(1);
148 }
149 Method setMethod = publicSetters.get(fieldName);
150 Method getMethod = publicGetters.get(fieldName);
151 PropertySetter setter = createPropertySetter(field, setMethod);
152 PropertyGetter getter = createPropertyGetter(field, getMethod);
153 setByQName.put(qname, setter);
154 setByLocalpart.put(localName, setter);
155 getByQName.put(qname, getter);
156 getByLocalpart.put(localName, getter);
157 }
158 if (this.elementLocalNameCollision) {
159 this.propertySetters = setByQName;
160 this.propertyGetters = getByQName;
161 elementDeclaredTypes = elementDeclaredTypesByQName;
162 } else {
163 this.propertySetters = setByLocalpart;
164 this.propertyGetters = getByLocalpart;
165 elementDeclaredTypes = elementDeclaredTypesByLocalpart;
166 }
167 }
168
169 static protected List<Field> getAllFields(Class<?> clz) {
170 List<Field> list = new ArrayList<Field>();
171 while (!Object.class.equals(clz)) {
172 list.addAll(Arrays.asList(getDeclaredFields(clz)));
173 clz = clz.getSuperclass();
174 }
175 return list;
176 }
177
178 static protected Field[] getDeclaredFields(final Class<?> clz) {
179 try {
180 return (System.getSecurityManager() == null) ? clz .getDeclaredFields() :
181 AccessController.doPrivileged(new PrivilegedExceptionAction<Field[]>() {
182 @Override
183 public Field[] run() throws IllegalAccessException {
184 return clz.getDeclaredFields();
185 }
186 });
187 } catch (PrivilegedActionException e) {
188 // TODO Auto-generated catch block
189 e.printStackTrace();
190 return null;
191 }
192 }
193
194 static protected PropertyGetter createPropertyGetter(Field field, Method getMethod) {
195 if (!field.isAccessible()) {
196 if (getMethod != null) {
197 MethodGetter methodGetter = new MethodGetter(getMethod);
198 if (methodGetter.getType().toString().equals(field.getType().toString())) {
199 return methodGetter;
200 }
201 }
202 }
203 return new FieldGetter(field);
204 }
205
206 static protected PropertySetter createPropertySetter(Field field,
207 Method setter) {
208 if (!field.isAccessible()) {
209 if (setter != null) {
210 MethodSetter injection = new MethodSetter(setter);
211 if (injection.getType().toString().equals(field.getType().toString())) {
212 return injection;
213 }
214 }
215 }
216 return new FieldSetter(field);
217 }
218
219 private Class getElementDeclaredType(QName name) {
220 Object key = (this.elementLocalNameCollision) ? name : name
221 .getLocalPart();
222 return elementDeclaredTypes.get(key);
223 }
224
225 @Override
226 public PropertyAccessor getPropertyAccessor(String ns, String name) {
227 final QName n = new QName(ns, name);
228 final PropertySetter setter = getPropertySetter(n);
229 final PropertyGetter getter = getPropertyGetter(n);
230 final boolean isJAXBElement = setter.getType()
231 .equals(JAXBElement.class);
232 final boolean isListType = java.util.List.class.isAssignableFrom(setter
233 .getType());
234 final Class elementDeclaredType = isJAXBElement ? getElementDeclaredType(n)
235 : null;
236 return new PropertyAccessor() {
237 @Override
238 public Object get(Object bean) throws DatabindingException {
239 Object val;
240 if (isJAXBElement) {
241 JAXBElement<Object> jaxbElement = (JAXBElement<Object>) getter.get(bean);
242 val = (jaxbElement == null) ? null : jaxbElement.getValue();
243 } else {
244 val = getter.get(bean);
245 }
246 if (val == null && isListType) {
247 val = new java.util.ArrayList();
248 set(bean, val);
249 }
250 return val;
251 }
252
253 @Override
254 public void set(Object bean, Object value) throws DatabindingException {
255 if (isJAXBElement) {
256 JAXBElement<Object> jaxbElement = new JAXBElement<Object>(
257 n, elementDeclaredType, contentClass, value);
258 setter.set(bean, jaxbElement);
259 } else {
260 setter.set(bean, value);
261 }
262 }
263 };
264 }
265 }
|
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
28 import java.lang.reflect.Array;
29 import java.lang.reflect.Field;
30 import java.lang.reflect.GenericArrayType;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.ParameterizedType;
33 import java.lang.reflect.Type;
34 import java.security.AccessController;
35 import java.security.PrivilegedActionException;
36 import java.security.PrivilegedExceptionAction;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.List;
42
43 import javax.xml.bind.JAXBElement;
44 import javax.xml.bind.annotation.XmlElement;
45 import javax.xml.bind.annotation.XmlElementRef;
46 import javax.xml.bind.annotation.XmlElementWrapper;
47 import javax.xml.namespace.QName;
48 import javax.xml.ws.WebServiceException;
49 import static com.sun.xml.internal.ws.spi.db.PropertyGetterBase.verifyWrapperType;
50
51 /**
52 * JAXBWrapperAccessor
53 *
54 * @author shih-chang.chen@oracle.com
55 */
56 @SuppressWarnings({ "unchecked", "rawtypes" })
57 public class JAXBWrapperAccessor extends WrapperAccessor {
58
59 protected Class<?> contentClass;
60 protected HashMap<Object, Class> elementDeclaredTypes;
61
62 public JAXBWrapperAccessor(Class<?> wrapperBean) {
63 verifyWrapperType(wrapperBean);
64 contentClass = (Class<?>) wrapperBean;
65
66 HashMap<Object, PropertySetter> setByQName = new HashMap<Object, PropertySetter>();
67 HashMap<Object, PropertySetter> setByLocalpart = new HashMap<Object, PropertySetter>();
68 HashMap<String, Method> publicSetters = new HashMap<String, Method>();
69
70 HashMap<Object, PropertyGetter> getByQName = new HashMap<Object, PropertyGetter>();
71 HashMap<Object, PropertyGetter> getByLocalpart = new HashMap<Object, PropertyGetter>();
72 HashMap<String, Method> publicGetters = new HashMap<String, Method>();
73
74 HashMap<Object, Class> elementDeclaredTypesByQName = new HashMap<Object, Class>();
75 HashMap<Object, Class> elementDeclaredTypesByLocalpart = new HashMap<Object, Class>();
76
77 for (Method method : contentClass.getMethods()) {
78 if (PropertySetterBase.setterPattern(method)) {
79 String key = method.getName()
80 .substring(3, method.getName().length()).toLowerCase();
81 publicSetters.put(key, method);
82 }
83 if (PropertyGetterBase.getterPattern(method)) {
128 Type arg = ((ParameterizedType) field.getGenericType())
129 .getActualTypeArguments()[0];
130 if (arg instanceof Class) {
131 elementDeclaredTypesByQName.put(qname, (Class) arg);
132 elementDeclaredTypesByLocalpart.put(localName,
133 (Class) arg);
134 } else if (arg instanceof GenericArrayType) {
135 Type componentType = ((GenericArrayType) arg)
136 .getGenericComponentType();
137 if (componentType instanceof Class) {
138 Class arrayClass = Array.newInstance(
139 (Class) componentType, 0).getClass();
140 elementDeclaredTypesByQName.put(qname, arrayClass);
141 elementDeclaredTypesByLocalpart.put(localName,
142 arrayClass);
143 }
144 }
145 }
146
147 }
148 Method setMethod = accessor(publicSetters, fieldName, localName);
149 Method getMethod = accessor(publicGetters, fieldName, localName);
150 if ( isProperty(field, getMethod, setMethod) ) {
151 PropertySetter setter = createPropertySetter(field, setMethod);
152 PropertyGetter getter = createPropertyGetter(field, getMethod);
153 setByQName.put(qname, setter);
154 setByLocalpart.put(localName, setter);
155 getByQName.put(qname, getter);
156 getByLocalpart.put(localName, getter);
157 }
158 }
159 if (this.elementLocalNameCollision) {
160 this.propertySetters = setByQName;
161 this.propertyGetters = getByQName;
162 elementDeclaredTypes = elementDeclaredTypesByQName;
163 } else {
164 this.propertySetters = setByLocalpart;
165 this.propertyGetters = getByLocalpart;
166 elementDeclaredTypes = elementDeclaredTypesByLocalpart;
167 }
168 }
169
170 static private Method accessor(HashMap<String, Method> map, String fieldName, String localName) {
171 Method a = map.get(fieldName);
172 if (a == null) a = map.get(localName);
173 if (a == null && fieldName.startsWith("_")) a = map.get(fieldName.substring(1));
174 return a;
175 }
176
177 static private boolean isProperty(Field field, Method getter, Method setter) {
178 if (java.lang.reflect.Modifier.isPublic(field.getModifiers())) return true;
179 if (getter == null) return false;
180 if (setter == null) {
181 return java.util.Collection.class.isAssignableFrom(field.getType()) ||
182 java.util.Map.class.isAssignableFrom(field.getType()) ;
183 } else {
184 return true;
185 }
186 }
187
188 static private List<Field> getAllFields(Class<?> clz) {
189 List<Field> list = new ArrayList<Field>();
190 while (!Object.class.equals(clz)) {
191 list.addAll(Arrays.asList(getDeclaredFields(clz)));
192 clz = clz.getSuperclass();
193 }
194 return list;
195 }
196
197 static private Field[] getDeclaredFields(final Class<?> clz) {
198 try {
199 return AccessController.doPrivileged(new PrivilegedExceptionAction<Field[]>() {
200 @Override
201 public Field[] run() throws IllegalAccessException {
202 return clz.getDeclaredFields();
203 }
204 });
205 } catch (PrivilegedActionException e) {
206 throw new WebServiceException(e);
207 }
208 }
209
210 static private PropertyGetter createPropertyGetter(Field field, Method getMethod) {
211 if (!field.isAccessible()) {
212 if (getMethod != null) {
213 MethodGetter methodGetter = new MethodGetter(getMethod);
214 if (methodGetter.getType().toString().equals(field.getType().toString())) {
215 return methodGetter;
216 }
217 }
218 }
219 return new PrivFieldGetter(field);
220 }
221
222 static private PropertySetter createPropertySetter(Field field,
223 Method setter) {
224 if (!field.isAccessible()) {
225 if (setter != null) {
226 MethodSetter injection = new MethodSetter(setter);
227 if (injection.getType().toString().equals(field.getType().toString())) {
228 return injection;
229 }
230 }
231 }
232 return new PrivFieldSetter(field);
233 }
234
235 private Class getElementDeclaredType(QName name) {
236 Object key = (this.elementLocalNameCollision) ? name : name
237 .getLocalPart();
238 return elementDeclaredTypes.get(key);
239 }
240
241 @Override
242 public PropertyAccessor getPropertyAccessor(String ns, String name) {
243 final QName n = new QName(ns, name);
244 final PropertySetter setter = getPropertySetter(n);
245 final PropertyGetter getter = getPropertyGetter(n);
246 final boolean isJAXBElement = setter.getType()
247 .equals(JAXBElement.class);
248 final boolean isListType = java.util.List.class.isAssignableFrom(setter
249 .getType());
250 final Class elementDeclaredType = isJAXBElement ? getElementDeclaredType(n)
251 : null;
252 return new PropertyAccessor() {
253 @Override
254 public Object get(Object bean) throws DatabindingException {
255 Object val;
256 if (isJAXBElement) {
257 JAXBElement<Object> jaxbElement = (JAXBElement<Object>) JAXBWrapperAccessor.get(getter, bean);
258 val = (jaxbElement == null) ? null : jaxbElement.getValue();
259 } else {
260 val = JAXBWrapperAccessor.get(getter, bean);
261 }
262 if (val == null && isListType) {
263 val = new java.util.ArrayList();
264 set(bean, val);
265 }
266 return val;
267 }
268
269 @Override
270 public void set(Object bean, Object value) throws DatabindingException {
271 if (isJAXBElement) {
272 JAXBElement<Object> jaxbElement = new JAXBElement<Object>(
273 n, elementDeclaredType, contentClass, value);
274 JAXBWrapperAccessor.set(setter, bean, jaxbElement);
275 } else {
276 JAXBWrapperAccessor.set(setter, bean, value);
277 }
278 }
279 };
280 }
281
282 static private Object get(PropertyGetter getter, Object wrapperInstance) {
283 return (getter instanceof PrivFieldGetter)?
284 ((PrivFieldGetter)getter).getPriv(wrapperInstance):
285 getter.get(wrapperInstance);
286 }
287
288 static private void set(PropertySetter setter, Object wrapperInstance, Object value) {
289 if (setter instanceof PrivFieldSetter)
290 ((PrivFieldSetter)setter).setPriv(wrapperInstance, value);
291 else
292 setter.set(wrapperInstance, value);
293 }
294
295
296 static private class PrivFieldSetter extends FieldSetter {
297 private PrivFieldSetter(Field f) {
298 super(f);
299 }
300 private void setPriv(final Object instance, final Object val) {
301 final Object resource = (type.isPrimitive() && val == null)? uninitializedValue(type): val;
302 if (field.isAccessible()) {
303 try {
304 field.set(instance, resource);
305 } catch (Exception e) {
306 throw new WebServiceException(e);
307 }
308 } else {
309 try {
310 AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
311 public Object run() throws IllegalAccessException {
312 if (!field.isAccessible()) {
313 field.setAccessible(true);
314 }
315 field.set(instance, resource);
316 return null;
317 }
318 });
319 } catch (PrivilegedActionException e) {
320 throw new WebServiceException(e);
321 }
322 }
323 }
324 }
325
326 static private class PrivFieldGetter extends FieldGetter {
327 private PrivFieldGetter(Field f) {
328 super(f);
329 }
330 static private class PrivilegedGetter implements PrivilegedExceptionAction {
331 private Object value;
332 private Field field;
333 private Object instance;
334 public PrivilegedGetter(Field field, Object instance) {
335 super();
336 this.field = field;
337 this.instance = instance;
338 }
339 public Object run() throws IllegalAccessException {
340 if (!field.isAccessible()) {
341 field.setAccessible(true);
342 }
343 value = field.get(instance);
344 return null;
345 }
346 }
347 private Object getPriv(final Object instance) {
348 if (field.isAccessible()) {
349 try {
350 return field.get(instance);
351 } catch (Exception e) {
352 throw new WebServiceException(e);
353 }
354 } else {
355 PrivilegedGetter privilegedGetter = new PrivilegedGetter(field, instance);
356 try {
357 AccessController.doPrivileged(privilegedGetter);
358 } catch (PrivilegedActionException e) {
359 throw new WebServiceException(e);
360 }
361 return privilegedGetter.value;
362 }
363 }
364 }
365 }
|