View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.xbean.spring.context.v2c;
18  
19  import java.beans.BeanInfo;
20  import java.beans.IntrospectionException;
21  import java.beans.Introspector;
22  import java.beans.PropertyDescriptor;
23  
24  import org.apache.xbean.spring.context.impl.PropertyEditorHelper;
25  import org.apache.xbean.spring.context.impl.QNameReflectionHelper;
26  import org.springframework.beans.factory.BeanDefinitionStoreException;
27  import org.springframework.beans.factory.config.BeanDefinition;
28  import org.springframework.beans.factory.support.AbstractBeanDefinition;
29  import org.springframework.beans.factory.xml.XmlReaderContext;
30  import org.w3c.dom.Element;
31  
32  public class XBeanQNameHelper {
33  
34      private XmlReaderContext readerContext;
35      
36      private boolean qnameIsOnClassPath;
37  
38      private boolean initQNameOnClassPath;
39      
40      public XBeanQNameHelper(XmlReaderContext readerContext) {
41          this.readerContext = readerContext;
42      }
43      
44      /**
45       * Any namespace aware property values (such as QNames) need to be coerced
46       * while we still have access to the XML Element from which its value comes -
47       * so lets do that now before we trash the DOM and just have the bean
48       * definition.
49       */
50      public void coerceNamespaceAwarePropertyValues(BeanDefinition definition, Element element) {
51          if (definition instanceof AbstractBeanDefinition && isQnameIsOnClassPath()) {
52              AbstractBeanDefinition bd = (AbstractBeanDefinition) definition;
53              // lets check for any QName types
54              BeanInfo beanInfo = getBeanInfo(bd.getBeanClassName());
55              if (beanInfo != null) {
56                  PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
57                  for (int i = 0; i < descriptors.length; i++) {
58                      QNameReflectionHelper.coerceNamespaceAwarePropertyValues(bd, element, descriptors, i);
59                  }
60              }
61          }
62      }
63  
64      public BeanInfo getBeanInfo(String className) throws BeanDefinitionStoreException {
65          if (className == null) {
66              return null;
67          }
68  
69          BeanInfo info = null;
70          Class type = null;
71          try {
72              type = loadClass(className);
73          }
74          catch (ClassNotFoundException e) {
75              throw new BeanDefinitionStoreException("Failed to load type: " + className + ". Reason: " + e, e);
76          }
77          try {
78              info = Introspector.getBeanInfo(type);
79          }
80          catch (IntrospectionException e) {
81              throw new BeanDefinitionStoreException("Failed to introspect type: " + className + ". Reason: " + e, e);
82          }
83          return info;
84      }
85  
86      /**
87       * Attempts to load the class on the current thread context class loader or
88       * the class loader which loaded us
89       */
90      protected Class loadClass(String name) throws ClassNotFoundException {
91          ClassLoader beanClassLoader = readerContext.getReader().getBeanClassLoader();
92          if (beanClassLoader != null) {
93              try {
94                  return beanClassLoader.loadClass(name);
95              }
96              catch (ClassNotFoundException e) {
97              }
98          }
99          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 }