001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.xbean.spring.context.v2c; 018 019 import java.beans.BeanInfo; 020 import java.beans.IntrospectionException; 021 import java.beans.Introspector; 022 import java.beans.PropertyDescriptor; 023 024 import org.apache.xbean.spring.context.impl.PropertyEditorHelper; 025 import org.apache.xbean.spring.context.impl.QNameReflectionHelper; 026 import org.springframework.beans.factory.BeanDefinitionStoreException; 027 import org.springframework.beans.factory.config.BeanDefinition; 028 import org.springframework.beans.factory.support.AbstractBeanDefinition; 029 import org.springframework.beans.factory.xml.XmlReaderContext; 030 import org.w3c.dom.Element; 031 032 public class XBeanQNameHelper { 033 034 private XmlReaderContext readerContext; 035 036 private boolean qnameIsOnClassPath; 037 038 private boolean initQNameOnClassPath; 039 040 public XBeanQNameHelper(XmlReaderContext readerContext) { 041 this.readerContext = readerContext; 042 } 043 044 /** 045 * Any namespace aware property values (such as QNames) need to be coerced 046 * while we still have access to the XML Element from which its value comes - 047 * so lets do that now before we trash the DOM and just have the bean 048 * definition. 049 */ 050 public void coerceNamespaceAwarePropertyValues(BeanDefinition definition, Element element) { 051 if (definition instanceof AbstractBeanDefinition && isQnameIsOnClassPath()) { 052 AbstractBeanDefinition bd = (AbstractBeanDefinition) definition; 053 // lets check for any QName types 054 BeanInfo beanInfo = getBeanInfo(bd.getBeanClassName()); 055 if (beanInfo != null) { 056 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); 057 for (int i = 0; i < descriptors.length; i++) { 058 QNameReflectionHelper.coerceNamespaceAwarePropertyValues(bd, element, descriptors, i); 059 } 060 } 061 } 062 } 063 064 public BeanInfo getBeanInfo(String className) throws BeanDefinitionStoreException { 065 if (className == null) { 066 return null; 067 } 068 069 BeanInfo info = null; 070 Class type = null; 071 try { 072 type = loadClass(className); 073 } 074 catch (ClassNotFoundException e) { 075 throw new BeanDefinitionStoreException("Failed to load type: " + className + ". Reason: " + e, e); 076 } 077 try { 078 info = Introspector.getBeanInfo(type); 079 } 080 catch (IntrospectionException e) { 081 throw new BeanDefinitionStoreException("Failed to introspect type: " + className + ". Reason: " + e, e); 082 } 083 return info; 084 } 085 086 /** 087 * Attempts to load the class on the current thread context class loader or 088 * the class loader which loaded us 089 */ 090 protected Class loadClass(String name) throws ClassNotFoundException { 091 ClassLoader beanClassLoader = readerContext.getReader().getBeanClassLoader(); 092 if (beanClassLoader != null) { 093 try { 094 return beanClassLoader.loadClass(name); 095 } 096 catch (ClassNotFoundException e) { 097 } 098 } 099 ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 100 if (contextClassLoader != null) { 101 try { 102 return contextClassLoader.loadClass(name); 103 } 104 catch (ClassNotFoundException e) { 105 } 106 } 107 return getClass().getClassLoader().loadClass(name); 108 } 109 110 protected boolean isQnameIsOnClassPath() { 111 if (initQNameOnClassPath == false) { 112 qnameIsOnClassPath = PropertyEditorHelper.loadClass("javax.xml.namespace.QName") != null; 113 initQNameOnClassPath = true; 114 } 115 return qnameIsOnClassPath; 116 } 117 118 }