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.lang.reflect.InvocationTargetException;
020 import java.lang.reflect.Method;
021
022 import org.apache.xbean.spring.context.impl.PropertyEditorHelper;
023 import org.apache.xbean.spring.context.impl.QNameReflectionHelper;
024 import org.apache.xbean.spring.context.v2.XBeanNamespaceHandler;
025 import org.springframework.beans.factory.config.BeanDefinition;
026 import org.springframework.beans.factory.support.AbstractBeanDefinition;
027 import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
028 import org.springframework.beans.factory.xml.XmlReaderContext;
029 import org.springframework.util.StringUtils;
030 import org.w3c.dom.Element;
031 import org.w3c.dom.Node;
032 import org.w3c.dom.NodeList;
033
034 public class XBeanBeanDefinitionParserDelegate extends BeanDefinitionParserDelegate {
035
036 public static final String QNAME_ELEMENT = "qname";
037
038 private XBeanQNameHelper qnameHelper;
039
040 public XBeanBeanDefinitionParserDelegate(XmlReaderContext readerContext) {
041 super(readerContext);
042 qnameHelper = new XBeanQNameHelper(readerContext);
043 }
044
045 public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultTypeClassName) {
046 if (!isDefaultNamespace(ele.getNamespaceURI())) {
047 return internalParseNestedCustomElement(ele, bd);
048 }
049 else if (ele.getTagName().equals(QNAME_ELEMENT)) {
050 return parseQNameElement(ele);
051 }
052 else {
053 return super.parsePropertySubElement(ele, bd, defaultTypeClassName);
054 }
055 }
056
057 public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
058 AbstractBeanDefinition bd = super.parseBeanDefinitionElement(ele, beanName, containingBean);
059 qnameHelper.coerceNamespaceAwarePropertyValues(bd, ele);
060 return bd;
061 }
062
063 public boolean isDefaultNamespace(String namespaceUri) {
064 return (!StringUtils.hasLength(namespaceUri) ||
065 BEANS_NAMESPACE_URI.equals(namespaceUri)) ||
066 XBeanNamespaceHandler.SPRING_SCHEMA.equals(namespaceUri) ||
067 XBeanNamespaceHandler.SPRING_SCHEMA_COMPAT.equals(namespaceUri);
068 }
069
070 protected Object parseQNameElement(Element element) {
071 return QNameReflectionHelper.createQName(element, getElementText(element));
072 }
073
074 protected String getElementText(Element element) {
075 StringBuffer buffer = new StringBuffer();
076 NodeList nodeList = element.getChildNodes();
077 for (int i = 0, size = nodeList.getLength(); i < size; i++) {
078 Node node = nodeList.item(i);
079 if (node.getNodeType() == Node.TEXT_NODE) {
080 buffer.append(node.getNodeValue());
081 }
082 }
083 return buffer.toString();
084 }
085
086 private Object internalParseNestedCustomElement(Element candidateEle, BeanDefinition containingBeanDefinition) {
087 try {
088 Method mth = getClass().getSuperclass().getDeclaredMethod("parseNestedCustomElement", new Class[] { Element.class, BeanDefinition.class });
089 mth.setAccessible(true);
090 return mth.invoke(this, new Object[] { candidateEle, containingBeanDefinition });
091 } catch (Exception e) {
092 if (e instanceof InvocationTargetException && e.getCause() instanceof RuntimeException) {
093 throw (RuntimeException) e.getCause();
094 }
095 throw (IllegalStateException) new IllegalStateException("Unable to invoke parseNestedCustomElement method").initCause(e);
096 }
097 }
098
099 }