blob: 1ad557931e11f2412ea5ada5dbd91e40f940f7c6 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xbean.spring.context.v2;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.SystemPropertyUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XBeanBeanDefinitionDocumentReader extends DefaultBeanDefinitionDocumentReader {
protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
BeanDefinitionParserDelegate delegate = XBeanV2Helper.createParser(readerContext);
delegate.initDefaults(root);
return delegate;
}
// introduced in Spring 3.1
protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = XBeanV2Helper.createParser(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
// introduced in Spring 4
protected BeanDefinitionParserDelegate createDelegate(XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
BeanDefinitionParserDelegate delegate = XBeanV2Helper.createParser(readerContext);
delegate.initDefaults(root, parentDelegate);
return delegate;
}
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
String namespaceUri = root.getNamespaceURI();
if (!DomUtils.nodeNameEquals(root, "beans") &&
!delegate.isDefaultNamespace(namespaceUri)) {
try {
try {
Method m = BeanDefinitionParserDelegate.class.getMethod("parseCustomElement", new Class[] { Element.class });
m.invoke(delegate, new Object[] { root });
} catch (NoSuchMethodException e) {
try {
Method m = BeanDefinitionParserDelegate.class.getMethod("parseCustomElement", new Class[] { Element.class, boolean.class });
m.invoke(delegate, new Object[] { root, Boolean.FALSE });
} catch (NoSuchMethodException e2) {
throw new IllegalStateException(e);
}
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw new RuntimeException(e);
}
} else if (DomUtils.nodeNameEquals(root, "beans")) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
String childNamespaceUri = ele.getNamespaceURI();
if (delegate.isDefaultNamespace(childNamespaceUri)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
} else {
super.parseBeanDefinitions(root, delegate);
}
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
}
/**
* Parse an "import" element and load the bean definitions
* from the given resource into the bean factory.
*/
protected void importBeanDefinitionResource(Element ele) {
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// Resolve system properties: e.g. "${user.dir}"
location = SystemPropertyUtils.resolvePlaceholders(location);
if (ResourcePatternUtils.isUrl(location)) {
int importCount = getReaderContext().getReader().loadBeanDefinitions(location);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
else {
// No URL -> considering resource location as relative to the current file.
try {
Resource relativeResource = getReaderContext().getResource().createRelative(location);
int importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error(
"Invalid relative resource location [" + location + "] to import bean definitions from", ele, null, ex);
}
}
getReaderContext().fireImportProcessed(location, extractSource(ele));
}
/**
* Process the given alias element, registering the alias with the registry.
*/
protected void processAliasRegistration(Element ele) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
boolean valid = true;
if (!StringUtils.hasText(name)) {
getReaderContext().error("Name must not be empty", ele);
valid = false;
}
if (!StringUtils.hasText(alias)) {
getReaderContext().error("Alias must not be empty", ele);
valid = false;
}
if (valid) {
try {
getReaderContext().getRegistry().registerAlias(name, alias);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(ex.getMessage(), ele);
}
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
}
}
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
}