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 */
017package org.apache.xbean.spring.context.v2;
018
019import java.util.Iterator;
020import java.util.List;
021
022import org.apache.xbean.spring.context.SpringApplicationContext;
023import org.apache.xbean.spring.context.SpringXmlPreprocessor;
024import org.springframework.beans.BeansException;
025import org.springframework.beans.factory.support.BeanDefinitionRegistry;
026import org.springframework.beans.factory.xml.NamespaceHandlerResolver;
027import org.springframework.beans.factory.xml.ResourceEntityResolver;
028import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
029import org.springframework.context.ApplicationContext;
030import org.springframework.core.io.Resource;
031import org.w3c.dom.Document;
032
033/**
034 * XBeanXmlBeanDefinitionReader extends XmlBeanDefinitionReader adds support for SpringXMLPreprocessors which can
035 * modify the DOM before it is passed to Spring for reading.  This allows for extra information to be added into the
036 * Spring configuration file that is processed and removed before Spring sees the xml.
037 *
038 * @author Dain Sundstrom
039 * @version $Id$
040 * @since 2.0
041 */
042public class XBeanXmlBeanDefinitionReader extends XmlBeanDefinitionReader {
043    private final SpringApplicationContext applicationContext;
044    private final List xmlPreprocessors;
045
046    /**
047     * Creates a XBeanXmlBeanDefinitionReader for the specified applicationContext and beanFactory which will apply
048     * the xmlPreprocessors before passing the DOM to Spring for processing.
049     * @param applicationContext the application context for which the bean definitons will be loaded
050     * @param beanFactory the beanFactory that services will be loaded
051     * @param xmlPreprocessors the preprocessors to apply the DOM before passing to Spring for processing
052     */
053    public XBeanXmlBeanDefinitionReader(SpringApplicationContext applicationContext, BeanDefinitionRegistry beanFactory, List xmlPreprocessors) {
054        super(beanFactory);
055        this.applicationContext = applicationContext;
056        this.xmlPreprocessors = xmlPreprocessors;
057        setNamespaceAware(true);
058        setValidationMode(VALIDATION_NONE);
059        if (applicationContext != null) {
060            setResourceLoader(applicationContext);
061            setEntityResolver(new ResourceEntityResolver(applicationContext));
062        }
063        setDocumentReaderClass(XBeanBeanDefinitionDocumentReader.class);
064    }
065
066    /**
067     * Gets the application context for which the bean definitons will be loaded.
068     * @return the application context for which the bean definitons will be loaded
069     */
070    public ApplicationContext getApplicationContext() {
071        return applicationContext;
072    }
073
074    /**
075     * {@inheritDoc}
076     */
077    public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
078        preprocess(doc);
079        return super.registerBeanDefinitions(doc, resource);
080    }
081
082    protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
083        ClassLoader classLoader = getBeanClassLoader();
084        if (classLoader == null) {
085            classLoader = Thread.currentThread().getContextClassLoader();
086        }
087        return new XBeanNamespaceHandlerResolver(classLoader);
088    }
089    
090    private void preprocess(Document doc) {
091        for (Iterator iterator = xmlPreprocessors.iterator(); iterator.hasNext();) {
092            SpringXmlPreprocessor preprocessor = (SpringXmlPreprocessor) iterator.next();
093            preprocessor.preprocess(applicationContext, this, doc);
094        }
095    }
096
097}