private void walkReferences(Class<?> cls) { if (cls == null) { return; } if (cls.getName().startsWith("java.") || cls.getName().startsWith("javax.")) { return; } // walk the public fields/methods to try and find all the classes. JAXB will only load the // EXACT classes in the fields/methods if they are in a different package. Thus, // subclasses won't be found and the xsi:type stuff won't work at all. // We'll grab the public field/method types and then add the ObjectFactory stuff // as well as look for jaxb.index files in those packages. XmlAccessType accessType = Utils.getXmlAccessType(cls); if (accessType != XmlAccessType.PROPERTY) { // only look for fields if we are instructed to // fields are accessible even if not public, must look at the declared fields // then walk to parents declared fields, etc... Field fields[] = ReflectionUtil.getDeclaredFields(cls); for (Field f : fields) { if (isFieldAccepted(f, accessType)) { XmlJavaTypeAdapter xjta = Utils.getFieldXJTA(f); if (xjta != null) { Type t = Utils.getTypeFromXmlAdapter(xjta); if (t != null) { addType(t); continue; } } addType(f.getGenericType()); } } walkReferences(cls.getSuperclass()); } if (accessType != XmlAccessType.FIELD) { // only look for methods if we are instructed to Method methods[] = ReflectionUtil.getDeclaredMethods(cls); for (Method m : methods) { if (isMethodAccepted(m, accessType)) { XmlJavaTypeAdapter xjta = Utils.getMethodXJTA(m); if (xjta != null) { Type t = Utils.getTypeFromXmlAdapter(xjta); if (t != null) { addType(t); continue; } } addType(m.getGenericReturnType()); for (Type t : m.getGenericParameterTypes()) { addType(t); } } } } }
private Map<String, BeanPair> getValuesFromBeanParam( Object bean, Class<? extends Annotation> annClass, Map<String, BeanPair> values) { for (Method m : bean.getClass().getMethods()) { if (m.getName().startsWith("set")) { try { String propertyName = m.getName().substring(3); Annotation annotation = m.getAnnotation(annClass); boolean beanParam = m.getAnnotation(BeanParam.class) != null; if (annotation != null || beanParam) { Method getter = bean.getClass().getMethod("get" + propertyName, new Class[] {}); Object value = getter.invoke(bean, new Object[] {}); if (value != null) { if (annotation != null) { String annotationValue = AnnotationUtils.getAnnotationValue(annotation); values.put(annotationValue, new BeanPair(value, m.getParameterAnnotations()[0])); } else { getValuesFromBeanParam(value, annClass, values); } } } else { String fieldName = StringUtils.uncapitalize(propertyName); Field f = InjectionUtils.getDeclaredField(bean.getClass(), fieldName); if (f == null) { continue; } annotation = f.getAnnotation(annClass); if (annotation != null) { Object value = ReflectionUtil.accessDeclaredField(f, bean, Object.class); if (value != null) { String annotationValue = AnnotationUtils.getAnnotationValue(annotation); values.put(annotationValue, new BeanPair(value, f.getAnnotations())); } } else if (f.getAnnotation(BeanParam.class) != null) { Object value = ReflectionUtil.accessDeclaredField(f, bean, Object.class); if (value != null) { getValuesFromBeanParam(value, annClass, values); } } } } catch (Throwable t) { // ignore } } } return values; }
private Exception convertFaultBean(Class<?> exClass, Object faultBean, Fault fault) throws Exception { Constructor<?> constructor = exClass.getConstructor(new Class[] {String.class}); Exception e = (Exception) constructor.newInstance(new Object[] {fault.getMessage()}); // Copy fault bean fields to exception for (Class<?> obj = exClass; !obj.equals(Object.class); obj = obj.getSuperclass()) { Field[] fields = obj.getDeclaredFields(); for (Field f : fields) { try { Field beanField = faultBean.getClass().getDeclaredField(f.getName()); ReflectionUtil.setAccessible(beanField); ReflectionUtil.setAccessible(f); f.set(e, beanField.get(faultBean)); } catch (NoSuchFieldException e1) { // do nothing } } } // also use/try public getter/setter methods Method meth[] = faultBean.getClass().getMethods(); for (Method m : meth) { if (m.getParameterTypes().length == 0 && (m.getName().startsWith("get") || m.getName().startsWith("is"))) { try { String name; if (m.getName().startsWith("get")) { name = "set" + m.getName().substring(3); } else { name = "set" + m.getName().substring(2); } Method m2 = exClass.getMethod(name, m.getReturnType()); m2.invoke(e, m.invoke(faultBean)); } catch (Exception e1) { // ignore } } } return e; }
private static Field getElField(String partName, final Class<?> wrapperType) { String fieldName = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.VARIABLE); Field[] fields = ReflectionUtil.getDeclaredFields(wrapperType); for (Field field : fields) { XmlElement el = field.getAnnotation(XmlElement.class); if (el != null && partName.equals(el.name())) { return field; } if (field.getName().equals(fieldName)) { return field; } } return null; }
private void initializeProperties() { BeanInfo beanInfo = null; try { if (beanClass.isInterface() || beanClass.isPrimitive()) { descriptors = getInterfacePropertyDescriptors(beanClass); } else if (beanClass == Object.class || beanClass == Throwable.class) { // do nothing } else if (beanClass == Throwable.class) { // do nothing } else if (Throwable.class.isAssignableFrom(beanClass)) { beanInfo = Introspector.getBeanInfo(beanClass, Throwable.class); } else if (RuntimeException.class.isAssignableFrom(beanClass)) { beanInfo = Introspector.getBeanInfo(beanClass, RuntimeException.class); } else if (Throwable.class.isAssignableFrom(beanClass)) { beanInfo = Introspector.getBeanInfo(beanClass, Throwable.class); } else { beanInfo = Introspector.getBeanInfo(beanClass, Object.class); } } catch (IntrospectionException e) { throw new DatabindingException("Couldn't introspect interface.", e); } if (beanInfo != null) { PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); if (propertyDescriptors != null) { // see comments on this function. descriptors = ReflectionUtil.getPropertyDescriptorsAvoidSunBug( getClass(), beanInfo, beanClass, propertyDescriptors); } } if (descriptors == null) { descriptors = new PropertyDescriptor[0]; } }
protected void processFaultDetail(Fault fault, Message msg) { Element exDetail = (Element) DOMUtils.getChild(fault.getDetail(), Node.ELEMENT_NODE); if (exDetail == null) { return; } QName qname = new QName(exDetail.getNamespaceURI(), exDetail.getLocalName()); FaultInfo faultWanted = null; MessagePartInfo part = null; BindingOperationInfo boi = msg.getExchange().get(BindingOperationInfo.class); if (boi == null) { return; } if (boi.isUnwrapped()) { boi = boi.getWrappedOperation(); } for (FaultInfo faultInfo : boi.getOperationInfo().getFaults()) { for (MessagePartInfo mpi : faultInfo.getMessageParts()) { if (qname.equals(mpi.getConcreteName())) { faultWanted = faultInfo; part = mpi; break; } } if (faultWanted != null) { break; } } if (faultWanted == null) { // did not find it using the proper qualified names, we'll try again with just the localpart for (FaultInfo faultInfo : boi.getOperationInfo().getFaults()) { for (MessagePartInfo mpi : faultInfo.getMessageParts()) { if (qname.getLocalPart().equals(mpi.getConcreteName().getLocalPart())) { faultWanted = faultInfo; part = mpi; break; } } if (faultWanted != null) { break; } } } if (faultWanted == null) { return; } Service s = msg.getExchange().get(Service.class); DataBinding dataBinding = s.getDataBinding(); Object e = null; if (isDOMSupported(dataBinding)) { DataReader<Node> reader = this.getNodeDataReader(msg); reader.setProperty(DataReader.FAULT, fault); e = reader.read(part, exDetail); } else { DataReader<XMLStreamReader> reader = this.getDataReader(msg); XMLStreamReader xsr = new W3CDOMStreamReader(exDetail); try { xsr.nextTag(); } catch (XMLStreamException e1) { throw new Fault(e1); } reader.setProperty(DataReader.FAULT, fault); e = reader.read(part, xsr); } if (!(e instanceof Exception)) { try { Class<?> exClass = faultWanted.getProperty(Class.class.getName(), Class.class); if (exClass == null) { return; } if (e == null) { Constructor<?> constructor = exClass.getConstructor(new Class[] {String.class}); e = constructor.newInstance(new Object[] {fault.getMessage()}); } else { try { Constructor<?> constructor = getConstructor(exClass, e); e = constructor.newInstance(new Object[] {fault.getMessage(), e}); } catch (NoSuchMethodException e1) { // Use reflection to convert fault bean to exception e = convertFaultBean(exClass, e, fault); } } msg.setContent(Exception.class, e); } catch (Exception e1) { LogUtils.log(LOG, Level.INFO, "EXCEPTION_WHILE_CREATING_EXCEPTION", e1, e1.getMessage()); } } else { if (fault.getMessage() != null) { Field f; try { f = Throwable.class.getDeclaredField("detailMessage"); ReflectionUtil.setAccessible(f); f.set(e, fault.getMessage()); } catch (Exception e1) { // ignore } } msg.setContent(Exception.class, e); } }
void addClass(Class<?> claz) { if (Throwable.class.isAssignableFrom(claz)) { if (!Throwable.class.equals(claz) && !Exception.class.equals(claz)) { walkReferences(claz); } addClass(String.class); } else if (claz.getName().startsWith("java.") || claz.getName().startsWith("javax.")) { return; } else { Class<?> cls = JAXBUtils.getValidClass(claz); if (cls == null && ReflectionUtil.getDeclaredConstructors(claz).length > 0 && !Modifier.isAbstract(claz.getModifiers())) { if (LOG.isLoggable(Level.INFO)) { LOG.info( "Class " + claz.getName() + " does not have a default constructor which JAXB requires."); } // there is no init(), but other constructors Object factory = createFactory(claz, ReflectionUtil.getDeclaredConstructors(claz)[0]); unmarshallerProperties.put("com.sun.xml.bind.ObjectFactory", factory); cls = claz; } if (null != cls) { if (classes.contains(cls)) { return; } if (!cls.isInterface()) { classes.add(cls); } XmlSeeAlso xsa = cls.getAnnotation(XmlSeeAlso.class); if (xsa != null) { for (Class<?> c : xsa.value()) { addClass(c); } } XmlJavaTypeAdapter xjta = cls.getAnnotation(XmlJavaTypeAdapter.class); if (xjta != null) { // has an adapter. We need to inspect the adapter and then // return as the adapter will handle the superclass // and interfaces and such Type t = Utils.getTypeFromXmlAdapter(xjta); if (t != null) { addType(t); } return; } if (cls.getSuperclass() != null) { // JAXB should do this, but it doesn't always. // in particular, older versions of jaxb don't addClass(cls.getSuperclass()); } if (!cls.isInterface()) { walkReferences(cls); } } } }
public WrapperHelper createWrapperHelper( Class<?> wrapperType, QName wrapperName, List<String> partNames, List<String> elTypeNames, List<Class<?>> partClasses) { List<Method> getMethods = new ArrayList<Method>(partNames.size()); List<Method> setMethods = new ArrayList<Method>(partNames.size()); List<Method> jaxbMethods = new ArrayList<Method>(partNames.size()); List<Field> fields = new ArrayList<Field>(partNames.size()); Method allMethods[] = wrapperType.getMethods(); String packageName = PackageUtils.getPackageName(wrapperType); // if wrappertype class is generated by ASM,getPackage() always return null if (wrapperType.getPackage() != null) { packageName = wrapperType.getPackage().getName(); } String objectFactoryClassName = packageName + ".ObjectFactory"; Object objectFactory = null; try { objectFactory = wrapperType.getClassLoader().loadClass(objectFactoryClassName).newInstance(); } catch (Exception e) { // ignore, probably won't need it } Method allOFMethods[]; if (objectFactory != null) { allOFMethods = objectFactory.getClass().getMethods(); } else { allOFMethods = new Method[0]; } for (int x = 0; x < partNames.size(); x++) { String partName = partNames.get(x); if (partName == null) { getMethods.add(null); setMethods.add(null); fields.add(null); jaxbMethods.add(null); continue; } String elementType = elTypeNames.get(x); String getAccessor = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.GETTER); String setAccessor = JAXBUtils.nameToIdentifier(partName, JAXBUtils.IdentifierType.SETTER); Method getMethod = null; Method setMethod = null; Class<?> valueClass = wrapperType; try { getMethod = valueClass.getMethod(getAccessor, AbstractWrapperHelper.NO_CLASSES); } catch (NoSuchMethodException ex) { // ignore for now } Field elField = getElField(partName, valueClass); if (getMethod == null && elementType != null && "boolean".equals(elementType.toLowerCase()) && (elField == null || (!Collection.class.isAssignableFrom(elField.getType()) && !elField.getType().isArray()))) { try { String newAcc = getAccessor.replaceFirst("get", "is"); getMethod = wrapperType.getMethod(newAcc, AbstractWrapperHelper.NO_CLASSES); } catch (NoSuchMethodException ex) { // ignore for now } } if (getMethod == null && "return".equals(partName)) { // RI generated code uses this try { getMethod = valueClass.getMethod("get_return", AbstractWrapperHelper.NO_CLASSES); } catch (NoSuchMethodException ex) { try { getMethod = valueClass.getMethod("is_return", new Class[0]); } catch (NoSuchMethodException ex2) { // ignore for now } } } if (getMethod == null && elField != null) { getAccessor = JAXBUtils.nameToIdentifier(elField.getName(), JAXBUtils.IdentifierType.GETTER); setAccessor = JAXBUtils.nameToIdentifier(elField.getName(), JAXBUtils.IdentifierType.SETTER); try { getMethod = valueClass.getMethod(getAccessor, AbstractWrapperHelper.NO_CLASSES); } catch (NoSuchMethodException ex) { // ignore for now } } String setAccessor2 = setAccessor; if ("return".equals(partName)) { // some versions of jaxb map "return" to "set_return" instead of "setReturn" setAccessor2 = "set_return"; } for (Method method : allMethods) { if (method.getParameterTypes() != null && method.getParameterTypes().length == 1 && (setAccessor.equals(method.getName()) || setAccessor2.equals(method.getName()))) { setMethod = method; break; } } getMethods.add(getMethod); setMethods.add(setMethod); if (setMethod != null && JAXBElement.class.isAssignableFrom(setMethod.getParameterTypes()[0])) { Type t = setMethod.getGenericParameterTypes()[0]; Class<?> pcls = null; if (t instanceof ParameterizedType) { t = ((ParameterizedType) t).getActualTypeArguments()[0]; } if (t instanceof Class) { pcls = (Class<?>) t; } String methodName = "create" + wrapperType.getSimpleName() + setMethod.getName().substring(3); for (Method m : allOFMethods) { if (m.getName().equals(methodName) && m.getParameterTypes().length == 1 && (pcls == null || pcls.equals(m.getParameterTypes()[0]))) { jaxbMethods.add(m); } } } else { jaxbMethods.add(null); } if (elField != null) { // JAXB Type get XmlElement Annotation XmlElement el = elField.getAnnotation(XmlElement.class); if (el != null && (partName.equals(el.name()) || "##default".equals(el.name()))) { ReflectionUtil.setAccessible(elField); fields.add(elField); } else { if (getMethod == null && setMethod == null) { if (el != null) { LOG.warning( "Could not create accessor for property " + partName + " of type " + wrapperType.getName() + " as the @XmlElement " + "defines the name as " + el.name()); } else { LOG.warning( "Could not create accessor for property " + partName + " of type " + wrapperType.getName()); } } fields.add(null); } } else { fields.add(null); } } return createWrapperHelper( wrapperType, setMethods.toArray(new Method[setMethods.size()]), getMethods.toArray(new Method[getMethods.size()]), jaxbMethods.toArray(new Method[jaxbMethods.size()]), fields.toArray(new Field[fields.size()]), objectFactory); }