aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.spi.db; aoqi@0: aoqi@0: import java.lang.reflect.Array; aoqi@0: import java.lang.reflect.Field; aoqi@0: import java.lang.reflect.GenericArrayType; aoqi@0: import java.lang.reflect.Method; aoqi@0: import java.lang.reflect.ParameterizedType; aoqi@0: import java.lang.reflect.Type; aoqi@0: import java.security.AccessController; aoqi@0: import java.security.PrivilegedActionException; aoqi@0: import java.security.PrivilegedExceptionAction; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Arrays; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.HashSet; aoqi@0: import java.util.List; aoqi@0: aoqi@0: import javax.xml.bind.JAXBElement; aoqi@0: import javax.xml.bind.annotation.XmlElement; aoqi@0: import javax.xml.bind.annotation.XmlElementRef; aoqi@0: import javax.xml.bind.annotation.XmlElementWrapper; aoqi@0: import javax.xml.namespace.QName; aoqi@0: aoqi@0: /** aoqi@0: * JAXBWrapperAccessor aoqi@0: * aoqi@0: * @author shih-chang.chen@oracle.com aoqi@0: */ aoqi@0: @SuppressWarnings({ "unchecked", "rawtypes" }) aoqi@0: public class JAXBWrapperAccessor extends WrapperAccessor { aoqi@0: aoqi@0: protected Class contentClass; aoqi@0: protected HashMap elementDeclaredTypes; aoqi@0: aoqi@0: public JAXBWrapperAccessor(Class wrapperBean) { aoqi@0: contentClass = (Class) wrapperBean; aoqi@0: aoqi@0: HashMap setByQName = new HashMap(); aoqi@0: HashMap setByLocalpart = new HashMap(); aoqi@0: HashMap publicSetters = new HashMap(); aoqi@0: aoqi@0: HashMap getByQName = new HashMap(); aoqi@0: HashMap getByLocalpart = new HashMap(); aoqi@0: HashMap publicGetters = new HashMap(); aoqi@0: aoqi@0: HashMap elementDeclaredTypesByQName = new HashMap(); aoqi@0: HashMap elementDeclaredTypesByLocalpart = new HashMap(); aoqi@0: aoqi@0: for (Method method : contentClass.getMethods()) { aoqi@0: if (PropertySetterBase.setterPattern(method)) { aoqi@0: String key = method.getName() aoqi@0: .substring(3, method.getName().length()).toLowerCase(); aoqi@0: publicSetters.put(key, method); aoqi@0: } aoqi@0: if (PropertyGetterBase.getterPattern(method)) { aoqi@0: String methodName = method.getName(); aoqi@0: String key = methodName.startsWith("is") ? methodName aoqi@0: .substring(2, method.getName().length()).toLowerCase() aoqi@0: : methodName.substring(3, method.getName().length()) aoqi@0: .toLowerCase(); aoqi@0: publicGetters.put(key, method); aoqi@0: } aoqi@0: } aoqi@0: HashSet elementLocalNames = new HashSet(); aoqi@0: for (Field field : getAllFields(contentClass)) { aoqi@0: XmlElementWrapper xmlElemWrapper = field.getAnnotation(XmlElementWrapper.class); aoqi@0: XmlElement xmlElem = field.getAnnotation(XmlElement.class); aoqi@0: XmlElementRef xmlElemRef = field.getAnnotation(XmlElementRef.class); aoqi@0: String fieldName = field.getName().toLowerCase(); aoqi@0: String namespace = ""; aoqi@0: String localName = field.getName(); aoqi@0: if (xmlElemWrapper != null) { aoqi@0: namespace = xmlElemWrapper.namespace(); aoqi@0: if (xmlElemWrapper.name() != null && !xmlElemWrapper.name().equals("") aoqi@0: && !xmlElemWrapper.name().equals("##default")) { aoqi@0: localName = xmlElemWrapper.name(); aoqi@0: } aoqi@0: }else if (xmlElem != null) { aoqi@0: namespace = xmlElem.namespace(); aoqi@0: if (xmlElem.name() != null && !xmlElem.name().equals("") aoqi@0: && !xmlElem.name().equals("##default")) { aoqi@0: localName = xmlElem.name(); aoqi@0: } aoqi@0: } else if (xmlElemRef != null) { aoqi@0: namespace = xmlElemRef.namespace(); aoqi@0: if (xmlElemRef.name() != null && !xmlElemRef.name().equals("") aoqi@0: && !xmlElemRef.name().equals("##default")) { aoqi@0: localName = xmlElemRef.name(); aoqi@0: } aoqi@0: } aoqi@0: if (elementLocalNames.contains(localName)) { aoqi@0: this.elementLocalNameCollision = true; aoqi@0: } else { aoqi@0: elementLocalNames.add(localName); aoqi@0: } aoqi@0: aoqi@0: QName qname = new QName(namespace, localName); aoqi@0: if (field.getType().equals(JAXBElement.class)) { aoqi@0: if (field.getGenericType() instanceof ParameterizedType) { aoqi@0: Type arg = ((ParameterizedType) field.getGenericType()) aoqi@0: .getActualTypeArguments()[0]; aoqi@0: if (arg instanceof Class) { aoqi@0: elementDeclaredTypesByQName.put(qname, (Class) arg); aoqi@0: elementDeclaredTypesByLocalpart.put(localName, aoqi@0: (Class) arg); aoqi@0: } else if (arg instanceof GenericArrayType) { aoqi@0: Type componentType = ((GenericArrayType) arg) aoqi@0: .getGenericComponentType(); aoqi@0: if (componentType instanceof Class) { aoqi@0: Class arrayClass = Array.newInstance( aoqi@0: (Class) componentType, 0).getClass(); aoqi@0: elementDeclaredTypesByQName.put(qname, arrayClass); aoqi@0: elementDeclaredTypesByLocalpart.put(localName, aoqi@0: arrayClass); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: // _return aoqi@0: if (fieldName.startsWith("_") && !localName.startsWith("_")) { aoqi@0: fieldName = fieldName.substring(1); aoqi@0: } aoqi@0: Method setMethod = publicSetters.get(fieldName); aoqi@0: Method getMethod = publicGetters.get(fieldName); aoqi@0: PropertySetter setter = createPropertySetter(field, setMethod); aoqi@0: PropertyGetter getter = createPropertyGetter(field, getMethod); aoqi@0: setByQName.put(qname, setter); aoqi@0: setByLocalpart.put(localName, setter); aoqi@0: getByQName.put(qname, getter); aoqi@0: getByLocalpart.put(localName, getter); aoqi@0: } aoqi@0: if (this.elementLocalNameCollision) { aoqi@0: this.propertySetters = setByQName; aoqi@0: this.propertyGetters = getByQName; aoqi@0: elementDeclaredTypes = elementDeclaredTypesByQName; aoqi@0: } else { aoqi@0: this.propertySetters = setByLocalpart; aoqi@0: this.propertyGetters = getByLocalpart; aoqi@0: elementDeclaredTypes = elementDeclaredTypesByLocalpart; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static protected List getAllFields(Class clz) { aoqi@0: List list = new ArrayList(); aoqi@0: while (!Object.class.equals(clz)) { aoqi@0: list.addAll(Arrays.asList(getDeclaredFields(clz))); aoqi@0: clz = clz.getSuperclass(); aoqi@0: } aoqi@0: return list; aoqi@0: } aoqi@0: aoqi@0: static protected Field[] getDeclaredFields(final Class clz) { aoqi@0: try { aoqi@0: return (System.getSecurityManager() == null) ? clz .getDeclaredFields() : aoqi@0: AccessController.doPrivileged(new PrivilegedExceptionAction() { aoqi@0: @Override aoqi@0: public Field[] run() throws IllegalAccessException { aoqi@0: return clz.getDeclaredFields(); aoqi@0: } aoqi@0: }); aoqi@0: } catch (PrivilegedActionException e) { aoqi@0: // TODO Auto-generated catch block aoqi@0: e.printStackTrace(); aoqi@0: return null; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static protected PropertyGetter createPropertyGetter(Field field, Method getMethod) { aoqi@0: if (!field.isAccessible()) { aoqi@0: if (getMethod != null) { aoqi@0: MethodGetter methodGetter = new MethodGetter(getMethod); aoqi@0: if (methodGetter.getType().toString().equals(field.getType().toString())) { aoqi@0: return methodGetter; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return new FieldGetter(field); aoqi@0: } aoqi@0: aoqi@0: static protected PropertySetter createPropertySetter(Field field, aoqi@0: Method setter) { aoqi@0: if (!field.isAccessible()) { aoqi@0: if (setter != null) { aoqi@0: MethodSetter injection = new MethodSetter(setter); aoqi@0: if (injection.getType().toString().equals(field.getType().toString())) { aoqi@0: return injection; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: return new FieldSetter(field); aoqi@0: } aoqi@0: aoqi@0: private Class getElementDeclaredType(QName name) { aoqi@0: Object key = (this.elementLocalNameCollision) ? name : name aoqi@0: .getLocalPart(); aoqi@0: return elementDeclaredTypes.get(key); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public PropertyAccessor getPropertyAccessor(String ns, String name) { aoqi@0: final QName n = new QName(ns, name); aoqi@0: final PropertySetter setter = getPropertySetter(n); aoqi@0: final PropertyGetter getter = getPropertyGetter(n); aoqi@0: final boolean isJAXBElement = setter.getType() aoqi@0: .equals(JAXBElement.class); aoqi@0: final boolean isListType = java.util.List.class.isAssignableFrom(setter aoqi@0: .getType()); aoqi@0: final Class elementDeclaredType = isJAXBElement ? getElementDeclaredType(n) aoqi@0: : null; aoqi@0: return new PropertyAccessor() { aoqi@0: @Override aoqi@0: public Object get(Object bean) throws DatabindingException { aoqi@0: Object val; aoqi@0: if (isJAXBElement) { aoqi@0: JAXBElement jaxbElement = (JAXBElement) getter.get(bean); aoqi@0: val = (jaxbElement == null) ? null : jaxbElement.getValue(); aoqi@0: } else { aoqi@0: val = getter.get(bean); aoqi@0: } aoqi@0: if (val == null && isListType) { aoqi@0: val = new java.util.ArrayList(); aoqi@0: set(bean, val); aoqi@0: } aoqi@0: return val; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void set(Object bean, Object value) throws DatabindingException { aoqi@0: if (isJAXBElement) { aoqi@0: JAXBElement jaxbElement = new JAXBElement( aoqi@0: n, elementDeclaredType, contentClass, value); aoqi@0: setter.set(bean, jaxbElement); aoqi@0: } else { aoqi@0: setter.set(bean, value); aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: } aoqi@0: }