Fri, 24 Oct 2014 15:02:28 +0200
8054367: More references for endpoints
Summary: fix also reviewed by Iaroslav.Savytskyi@oracle.com, Alexander.Fomin@oracle.com
Reviewed-by: mullan, skoivu
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
23 * questions.
24 */
26 package com.sun.xml.internal.ws.spi.db;
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;
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;
49 /**
50 * JAXBWrapperAccessor
51 *
52 * @author shih-chang.chen@oracle.com
53 */
54 @SuppressWarnings({ "unchecked", "rawtypes" })
55 public class JAXBWrapperAccessor extends WrapperAccessor {
57 protected Class<?> contentClass;
58 protected HashMap<Object, Class> elementDeclaredTypes;
60 public JAXBWrapperAccessor(Class<?> wrapperBean) {
61 contentClass = (Class<?>) wrapperBean;
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>();
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>();
71 HashMap<Object, Class> elementDeclaredTypesByQName = new HashMap<Object, Class>();
72 HashMap<Object, Class> elementDeclaredTypesByLocalpart = new HashMap<Object, Class>();
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)) {
81 String methodName = method.getName();
82 String key = methodName.startsWith("is") ? methodName
83 .substring(2, method.getName().length()).toLowerCase()
84 : methodName.substring(3, method.getName().length())
85 .toLowerCase();
86 publicGetters.put(key, method);
87 }
88 }
89 HashSet<String> elementLocalNames = new HashSet<String>();
90 for (Field field : getAllFields(contentClass)) {
91 XmlElementWrapper xmlElemWrapper = field.getAnnotation(XmlElementWrapper.class);
92 XmlElement xmlElem = field.getAnnotation(XmlElement.class);
93 XmlElementRef xmlElemRef = field.getAnnotation(XmlElementRef.class);
94 String fieldName = field.getName().toLowerCase();
95 String namespace = "";
96 String localName = field.getName();
97 if (xmlElemWrapper != null) {
98 namespace = xmlElemWrapper.namespace();
99 if (xmlElemWrapper.name() != null && !xmlElemWrapper.name().equals("")
100 && !xmlElemWrapper.name().equals("##default")) {
101 localName = xmlElemWrapper.name();
102 }
103 }else if (xmlElem != null) {
104 namespace = xmlElem.namespace();
105 if (xmlElem.name() != null && !xmlElem.name().equals("")
106 && !xmlElem.name().equals("##default")) {
107 localName = xmlElem.name();
108 }
109 } else if (xmlElemRef != null) {
110 namespace = xmlElemRef.namespace();
111 if (xmlElemRef.name() != null && !xmlElemRef.name().equals("")
112 && !xmlElemRef.name().equals("##default")) {
113 localName = xmlElemRef.name();
114 }
115 }
116 if (elementLocalNames.contains(localName)) {
117 this.elementLocalNameCollision = true;
118 } else {
119 elementLocalNames.add(localName);
120 }
122 QName qname = new QName(namespace, localName);
123 if (field.getType().equals(JAXBElement.class)) {
124 if (field.getGenericType() instanceof ParameterizedType) {
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 }
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 }
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 }
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 }
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 }
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 }
219 private Class getElementDeclaredType(QName name) {
220 Object key = (this.elementLocalNameCollision) ? name : name
221 .getLocalPart();
222 return elementDeclaredTypes.get(key);
223 }
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 }
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 }